Beautiful numbers

题目链接:https://vjudge.net/problem/CodeForces-55D

题意:有T组数据,每组数据输入两个数,a,b,输出在a-b区间有多少个美丽数
美丽数:规定一个数它能被它各个位上非0数整除,即为美丽数。
 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #define LL long long
 7 using namespace std;
 8 int num[2550],cnt=0;
 9 int lim[50],lct=0;
10 LL f[24][2520][50];
11 LL n,m;
12 LL gcd(LL a,LL b)
13 {
14     if(!b)
15        return a;
16     return gcd(b,a%b);
17 }
18 LL dp(int pos,int smm,int lcm,bool flag)
19 {
20 ///当前位置 当前和 当前最小公倍数 是否在上界(flag==0时达到上界)
21     if(pos==0)
22         return smm%lcm==0;///当前的和能整除当前最小公倍数则返回1
23     if(flag==0&&f[pos][smm][num[lcm]]!=-1)
24         return f[pos][smm][num[lcm]];
25     LL res=0;
26     int limit=9;
27     if(flag)
28        limit=lim[pos];
29     for(int i=0;i<=limit;i++)///0到limit,即能完成找出0到数x的全部beautifui numbers
30     {
31        int psmm=(smm*10+i)%2520;
32        int plcm=lcm;
33        if(i)
34        {
35           plcm=lcm/gcd(lcm,i)*i;
36        }
37        res+=dp(pos-1,psmm,plcm,flag&&i==limit);///flag&&i==limit的意思是比如100要把100以前所有的数也要算一遍,控制flag是否等于0判断是否让limit=lim[pos],例如100,第一位limit=1,进如for循环,i=0时,flag=0,再次进如dp是limit才能等于9
38     }
39     if(flag==0)
40     f[pos][smm][num[lcm]]=res;
41     return res;
42 }
43 LL divi(LL x)///该函数是求在x之前有多少个beautiful number
44 {
45    lct=0;///lct是记录x有多少位
46    while(x)
47    {
48       lim[++lct]=x%10;///lim数组是记录各个位上的数
49       x/=10;
50       printf("%d\n",lim[lct]);
51    }
52    return dp(lct,0,1,1);
53 }
54 int main()
55 {
56     int t;
57     for(i=1;i<=2520;i++)
58     {
59         if(2520%i==0)
60             num[i]=++cnt;
61     }
62     memset(f,-1,sizeof(f));
63     scanf("%d",&t);
64     while(t--)
65     {
66           scanf("%I64d%I64d",&n,&m);
67           printf("%I64d\n",divi(m)-divi(n-1));
68     }
69 }
原文地址:https://www.cnblogs.com/shanshuiyouxiangfeng/p/7819446.html