Codeforces 55D Beautiful numbers
题意:统计某段区间内满足它所有非零数位能整除这个数本身的数的个数。
解法;
自己搞的时候除了想到开N维数组分别记录之外没什么别的想法><
2~9所有数的lcm最大是2520,dp[pos][pre_mod][pre_lcm]记录前pos位数对2520取余为pre_mod并且非零位的lcm位pre_lcm的个数。
因为2到9的lcm最多只有不到50个,我们需要对lcm离散化一下。。。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define N 25 6 using namespace std; 7 typedef long long ll; 8 const int maxn=2600; 9 const int mod=2520; 10 ll dp[N][maxn][50]; 11 int hash[maxn]; 12 int bit[N]; 13 void init(){ 14 int cnt=0; 15 for(int i=1;i<=mod;i++){ 16 if(mod%i==0){ 17 hash[i]=++cnt; 18 } 19 } 20 } 21 int gcd(int a,int b){ 22 for(int r=a%b;r;a=b,b=r,r=a%b); 23 return b; 24 } 25 int lcm(int a,int b){ 26 return a/gcd(a,b)*b; 27 } 28 ll dfs(int pos,int pre_mod,int pre_lcm,bool flag){ 29 if(pos==0)return pre_mod%pre_lcm==0; 30 if(flag&&~dp[pos][pre_mod][hash[pre_lcm]])return dp[pos][pre_mod][hash[pre_lcm]]; 31 int u=flag?9:bit[pos]; 32 ll ans=0; 33 int next_mod,next_lcm; 34 for(int d=0;d<=u;d++){ 35 next_mod=(pre_mod*10+d)%mod; 36 next_lcm=pre_lcm; 37 if(d)next_lcm=lcm(pre_lcm,d); 38 ans+=dfs(pos-1,next_mod,next_lcm,flag||d<u); 39 } 40 if(flag)dp[pos][pre_mod][hash[pre_lcm]]=ans; 41 return ans; 42 } 43 ll solve(ll n){ 44 int len=0; 45 while(n>0){ 46 bit[++len]=n%10; 47 n/=10; 48 } 49 return dfs(len,0,1,0); 50 } 51 int main(){ 52 init(); 53 int t; 54 ll l,r; 55 cin>>t; 56 memset(dp,-1,sizeof(dp)); 57 while(t--){ 58 cin>>l>>r; 59 ll ans=solve(r)-solve(l-1); 60 cout<<ans<<endl; 61 } 62 return 0; 63 }