如果一个数能够被组成它的各个非0数字整除,则称它是完美数。例如:1-9都是完美数,10,11,12,101都是完美数,但是13就不是完美数(因为13不能被数字3整除)。
现在给定正整数x,y,求x和y之间(包含x和y的闭区间)共有多少完美数。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行2个数,X, Y中间用空格分割。(1 <= X <= Y <= 10^18)
Output
输出共T行,对应区间中完美数的数量。
1..10的lcm为2520,从1..10里选若干个数的lcm个数只有四十多个。。
f[i][j][k]表示十进制下长度为i位的数字里,那个数字模2520后的值为j的倍数,数位上各个非0数字的lcm为第k种。
之后就是正常的数位DP了。
一开始不会做是因为状态表示得不对...第二维没有考虑倍数...结果统计的复杂度就上天了...
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #define ll long long 9 #define ull unsigned long long 10 #define ui unsigned int 11 //#define d double 12 #define ld long double 13 const int maxn=404,inf=1002333333; 14 ll f[20][2523][49]; 15 int NEXT[2523][10],LCM[2523][10],id[2523],num[233]; 16 int i,j,k,n,m,s,t,ans; 17 18 int ra,fh;char rx; 19 inline int read(){ 20 rx=getchar(),ra=0,fh=1; 21 while(rx<'0'&&rx!='-')rx=getchar(); 22 if(rx=='-')fh=-1,rx=getchar(); 23 while(rx>='0')ra=ra*10+rx-48,rx=getchar();return ra*fh; 24 } 25 26 inline int gcd(int a,int b){return !b?a:gcd(b,a%b);} 27 inline void pre(){ 28 int i,j,tmp=0; 29 memset(f,255,sizeof(f)); 30 for(i=1;i<=2520;i++){ 31 if(!(2520%i))id[i]=++tmp; 32 LCM[i][0]=LCM[i][1]=i; 33 for(j=2;j<=9;j++)LCM[i][j]=i*j/gcd(i,j); 34 } 35 for(i=0;i<2520;i++)for(j=0;j<=9;j++)NEXT[i][j]=(i*10+j)%2520; 36 } 37 ll dfs(int i,int p,int lcm,bool pr){ 38 if(i<0)return !(p%lcm); 39 if(!pr&&f[i][p][id[lcm]]!=-1)return f[i][p][id[lcm]]; 40 int mx=!pr?9:num[i];ll tmp=0; 41 for(int j=0;j<=mx;j++) 42 tmp+=dfs(i-1,NEXT[p][j],LCM[lcm][j],pr&&j==mx); 43 if(!pr)f[i][p][id[lcm]]=tmp; 44 return tmp; 45 } 46 inline ll get(ll x){ 47 int len=0;while(x)num[len++]=x%10,x/=10; 48 return dfs(len-1,0,1,1); 49 } 50 int main(){ 51 pre();ll l,r; 52 for(int t=read();t;t--) 53 scanf("%lld%lld",&l,&r), 54 printf("%lld\n",get(r)-get(l-1)); 55 }