55 D Beautiful numbers
制約条件
t≦10
l[i],r[i]≦9*10^18
方針
95 D Horse Racesとほぼ同じ。
各桁でその和が割り切れる数というのは、DPで、
「いままでに出現した1〜9のフラグ」、「いままでの数のmod2520でのあまり」を
覚えながらテーブルを更新することで求まる。
見ている数より小さい数になった場合メモ化をし、そうでないときはメモ化をしないことでDPテーブルが全てのl[i],r[i]について使いまわせるようになる。
ソースコード
ll dp[20][2520][4*3*2*2];//2(3乗まで), 3(2乗まで), 5(1乗まで), 7(1乗まで) ll rec(char *s,int p,int mod,int e,bool small){ if(small&&dp[p][mod][e]>=0)return dp[p][mod][e]; int two=e%4, three=e/4%3, five=e/12%2, seven=e/24; if(p==19){ int tmp=1; rep(i,two)tmp*=2; rep(i,three)tmp*=3; rep(i,five)tmp*=5; rep(i,seven)tmp*=7; return mod%tmp==0; } ll ret=0; rep(i,10){ int nmod=(mod*10+i)%2520, ne; bool nsmall=small||i<s[p]-'0'; int t2=0,t3=0,t5=0,t7=0; for(int m=i;m&&m%2==0;m/=2)t2++; for(int m=i;m&&m%3==0;m/=3)t3++; for(int m=i;m&&m%5==0;m/=5)t5++; for(int m=i;m&&m%7==0;m/=7)t7++; t2=max(two,t2); t3=max(three,t3); t5=max(five,t5); t7=max(seven,t7); ne=t2+t3*4+t5*12+t7*24; if(nsmall||i==s[p]-'0')ret+=rec(s,p+1,nmod,ne,nsmall); } if(small)dp[p][mod][e]=ret; return ret; } void run() { memset(dp,-1,sizeof(dp)); int t; cin>>t; rep(i,t){ ll a,b; cin>>a>>b; a--; char A[20],B[20]; sprintf(A,"%019I64d",a); sprintf(B,"%019I64d",b); cout<<rec(B,0,0,0,0)-rec(A,0,0,0,0)<<endl; } }