BZOJ 3679 数位DP
思路:
f[i][j]表示i位数乘积为j的方案数
j的取值最多5000多种,那就开个map存一下好了
f[i][mp[k*rec[j]]]+=f[i-1][j];
//By SiriusRen #include <map> #include <cstdio> using namespace std; #define int long long int n,L,R,tot,rec[6666],f[20][6666]; map<int,int>mp; void dfs(int x){ if(x>n||mp.find(x)!=mp.end())return; mp[x]=++tot,rec[tot]=x; for(int i=2;i<=9;i++)dfs(x*i); } map<int,int>::iterator it; int calc(int m){ int p=1,base=0,now=1,ans=0; for(;10*p<=m;base++,p*=10); for(int i=1;i<=base;i++) for(int j=1;j<=tot;j++) ans+=f[i][j]; for(int i=base;i>=0;i--){ for(int j=1;j<=tot;j++) for(int k=1;k<m/p;k++) if(rec[j]*k*now<=n) ans+=f[i][j]; now=m/p*now,m%=p,p/=10; if(!now)return ans; } return ans+(now<=n); } signed main(){ scanf("%lld%lld%lld",&n,&L,&R); dfs(1),f[0][1]=1; for(int i=1;i<=18;i++) for(int j=1;j<=tot;j++) for(int k=1;k<=9;k++) if(k*rec[j]<=n)f[i][mp[k*rec[j]]]+=f[i-1][j]; printf("%lld\n",calc(R-1)-calc(L-1)); }