-
A - Beautiful numbers
- CodeForces - 55D
- 题意: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; }
A - Beautiful numbers-取模数位DP
最新推荐文章于 2021-01-13 22:23:33 发布