Codeforces Beta Round #51 D. Beautiful numbers(数位dp)

来源:互联网 发布:linux 中文字体 编辑:程序博客网 时间:2024/06/09 23:05

题目链接

问区间[L,R] 之间有多少个数满足,这个数能够整除这个数的每一个数位,比如36可以整除3和6,所以是符合要求的数字。

直接看来,一个数每一位还没有确定的时候,就无法知道这个数能不能整除自己的每一位。

假如这个数是可以整除自己的每一位,也就是说这个数是自己每一位的公倍数,比如一个满足的数X组成是abc的形式,那么X是a的倍数,b的倍数,c的倍数,也就是X%lcm(a,b,c)==0。然后1-9的lcm是2520,也就是2520能整除1-9的任意组合,利用这些性质,就可以进行空间的压缩离散

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define LL long long#define gcd __gcd#define LCM(x,y) x/gcd(x,y)*y#define dbg(x) printf("deg: # ::: %d\n",x);#define cl(a,b) memset(a,b,sizeof(a))const int maxn = 1005;LL dp[20][2521][50];int Lcm[2521];//离散 保证dp可以开下空间int bit[20];void init(){    for(int i=1,j=0;i<=2520;i++)if(2520%i==0)        Lcm[i]=j++;}LL dfs(int i,int s,int lm,bool e){    if(i == 0) return s % lm== 0;    if(!e && ~dp[i][s][Lcm[lm]]) return dp[i][s][Lcm[lm]];    LL ans = 0;    int u = e?bit[i]:9;    for(int d=0;d<=u;d++){        ans+=dfs(i-1,(s*10+d)%2520,d?LCM(lm,d):lm,e&&d==u);    }    return e?ans:dp[i][s][Lcm[lm]]=ans;}LL f(LL num){    int len=0;    while(num){        bit[++len]=num%10;        num/=10;    }    return dfs(len,0,1,1);}int main(){    int T;init();    scanf("%d",&T);cl(dp,-1);    while(T--){        LL L,R;scanf("%lld%lld",&L,&R);        printf("%lld\n",f(R)-f(L-1));    }    return 0;}
0 0
原创粉丝点击