首页 > 其他 > 详细

CF 55D - Beautiful numbers(数位DP)

时间:2015-07-25 11:57:22      阅读:236      评论:0      收藏:0      [点我收藏+]

题意:

如果一个数能被自己各个位的数字整除,那么它就叫 Beautiful numbers。
求区间 [a,b] 中 Beautiful numbers 的个数。

分析:先分析出,2~9 的最大的最小公倍数是 2520({5,7,8,9}),先预处理出所有可能的最小公倍数m[c]

dp[i][d][c]表示长度i, 余数d,最小公倍数是m[c]的个数。

#include<cstdio>
#include<cstring>
#define mod 2520
ll dp[35][2520][100];
int bit[64],m[200],mnum;
int gcd(int a,int b){
    int tmp;
    while(a%b){
        tmp=b;
        b=a%b;
        a=tmp;
    }
    return b;
}
int lcm(int a,int b){
    return a*b/gcd(a,b);
}
//查最小公倍数的标号
int tfind(int x){ int ll=1,rr=mnum; while(ll<=rr){ int mid=(ll+rr)>>1; if(m[mid]<x)ll=mid+1; else rr=mid-1; } return ll; } void init(){ memset(dp,-1,sizeof(dp)); mnum=0; for(int i=1;i<=mod;++i) if(mod%i==0) m[++mnum]=i; } ll dfs(int i,int d,int c,int e){ if(i==0)return d%m[c]?0:1; if(!e&&dp[i][d][c]!=-1)return dp[i][d][c]; int l=e?bit[i]:9; ll num=0; for(int j=0;j<=l;++j) { int td=(d*10+j)%mod; int tc=c; if(j)tc=tfind(lcm(m[c],j)); num+=dfs(i-1,td,tc,e&&(j==l)); } return e?num:dp[i][d][c]=num; } ll solve(ll x){ int len=0; while(x){ bit[++len]=x%10; x/=10; } return dfs(len,0,1,1); } int main() { int t; scanf("%d",&t); init(); ll x,y; while(t--){ scanf("%I64d%I64d",&x,&y); printf("%I64d\n",solve(y)-solve(x-1)); } return 0; }

 

CF 55D - Beautiful numbers(数位DP)

原文:http://www.cnblogs.com/zsf123/p/4675475.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!