码迷,mamicode.com
首页 > 其他好文 > 详细

CF 55D - Beautiful numbers(数位DP)

时间:2015-07-25 11:58:11      阅读:93      评论: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
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!