Beautiful numbers-取模數位DP
阿新 • • 發佈:2018-12-13
- 題意:It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits
- 在他看來,正整數是優美的,當且僅當它是由它的每個非零數字整除時。
- zyl思路:數位DP時我們只需儲存前面那些位的最小公倍數就可進行狀態轉移,到邊界時就把所有位的lcm求出了,為了判斷這個數能否被它的所有數位整除,我們還需要這個數的值,顯然要記錄值是不可能的,其實我們只需記錄它對2520的模即可,這樣我們就可以設計出如下數位DP:dfs(pos,mod,lcm,f),pos為當前位,mod為前面那些位對2520的模,lcm為前面那些數位的最小公倍數,f標記前面那些位是否達到上限,這樣一來dp陣列就要開到19*2520*2520,明顯超記憶體了,考慮到最小公倍數是離散的,1-2520中可能是最小公倍數的其實只有48個,經過離散化處理後,dp陣列的最後一維可以降到48,這樣就不會超了
-
#include <iostream> #include <cstring> using namespace std; long long dp[40][2530][50]; int ls[3000],cnt=0; int f[30],k; int gcd(int a,int b) { return a==0 ? b:gcd(b%a,a); } long long dfs(int pos,int mod,int lcm,bool flag) { if(pos==0)return mod%lcm==0; if(!flag&&dp[pos][mod][ls[lcm]]!=-1)return dp[pos][mod][ls[lcm]]; int maxx=9; if(flag)maxx=f[pos]; long long ans=0; for(int i=0; i<=maxx; i++) { int modd=(mod*10+i)%2520; int lcmm=lcm; if(i!=0) { lcmm=lcm/(gcd(lcm,i))*i; } ans+=dfs(pos-1,modd,lcmm,flag&&i==maxx); } if(!flag)dp[pos][mod][ls[lcm]]=ans; return ans; } long long solve(long long x) { k=0; while(x) { f[++k]=x%10; x=x/10; } return dfs(k,0,1,1); } int main() { for(int i=1; i<=2520; i++) { if(2520%i==0) { ls[i]=++cnt; } } memset(dp,-1,sizeof(dp)); int t; cin>>t; while(t--) { long long a,b; cin>>a>>b; long long ans=solve(b)-solve(a-1); cout<<ans<<endl; } return 0; }