题目链接:http://codeforces.com/problemset/problem/55/D
很裸的数位$DP$但是要考虑一下如何设计状态保证复杂度且不会爆掉空间...
提供一种很暴力的状态表示
${f[len][zt][res]}$表示从高位往地位确定到了第$len$位,是否选取了${2..9}$这些数字状压为$zt$(因为${0,1}$不影响判定),数字模$2520$的值为$res$的数字有多少个。
${gcd(2,3,4,5,6,7,8,9)=2520}$
然后记忆化一下就可以了,
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 10010 10 #define llg int 11 #define SIZE (1<<8) 12 #define LL long long 13 #define md 2520 14 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 15 llg n,m,c[100],T; 16 llg p[8]={2,3,4,5,6,7,8,9}; 17 LL f[20][SIZE+1][2520]; 18 19 inline llg getint() 20 { 21 llg w=0,q=0; char c=getchar(); 22 while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar(); if(c==‘-‘) q=1,c=getchar(); 23 while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar(); return q ? -w : w; 24 } 25 26 LL dfs(llg len,llg zt,llg res,bool flag) 27 { 28 if (!len) 29 { 30 for (llg i=0;i<8;i++) 31 if (zt&(1<<i) && res%(i+2)!=0) 32 return 0; 33 return 1; 34 } 35 if (!flag && f[len][zt][res]!=-1) return f[len][zt][res]; 36 llg up; 37 LL sum=0; 38 if (flag) up=c[len];else up=9; 39 for (llg i=0;i<=up;i++) 40 { 41 llg nezt,neres; 42 if (i>1) nezt=zt|(1<<(i-2)); else nezt=zt; 43 neres=(res*10+i)%md; 44 sum+=dfs(len-1,nezt,neres,(flag && i==up)); 45 } 46 if (!flag) f[len][zt][res]=sum; 47 return sum; 48 } 49 50 LL dp(LL x) 51 { 52 if (x==0) return 1; 53 llg wei=0; 54 while (x) 55 { 56 c[++wei]=x%10; 57 x/=10; 58 } 59 return dfs(wei,0,0,1); 60 } 61 62 int main() 63 { 64 //yyj("number"); 65 cin>>T; 66 LL a,b; 67 memset(f,-1,sizeof(f)); 68 while (T--) 69 { 70 scanf("%lld%lld",&a,&b); 71 printf("%lld\n",dp(b)-dp(a-1)); 72 } 73 return 0; 74 }
时间: 2024-10-08 08:02:28