Describe
题目链接
给出两个数$a,b$,求出$[a,b]$中各位数字之和能整除原数的数的个数。
Solution
数位dp。
$DFS(x,sum,dig,lim)$分别表示第$x$位,当前数位之和为$sum$,数字为$dig$,是否到达极限。
但是数据极大,$dig$会达到${10}^{18}$是不可能来记忆化的,所以考虑取模
那么模多少好呢?很明显如果模$sum$是最好的,最后只要判断下是否等于$0$即可。
那么暴力跑$9\times len$次数位$dp$,求的是$sum==i$时的数位$dp$结果,最后加起来就好了。
P.S.这里参考了讨论区神仙的优化:如果最后各个数位之和绝对到不了要求的话直接$return 0$。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include<bits/stdc++.h> #define int long long using namespace std; int a[21],m,mod,f[21][201][201][2]; inline int DFS(int x,int sum,int dig,int lim){ if(sum+9*x<mod) return 0; if(x==0) return sum==mod&&dig==0; if(~f[x][sum][dig][lim]) return f[x][sum][dig][lim]; int Max=lim?a[x]:9,res=0; for(int i=0;i<=Max;i++) res+=DFS(x-1,sum+i,(dig*10+i)%mod,lim&&(i==Max)); return f[x][sum][dig][lim]=res; } inline int solve(int n){ m=0; while(n){ a[++m]=n%10; n/=10; } int res=0; for(mod=1;mod<=m*9;mod++) memset(f,-1,sizeof(f)),res+=DFS(m,0,0,1); return res; } int L,R; signed main(){return scanf("%lld%lld",&L,&R),printf("%lld\n",solve(R)-solve(L-1)),0;}
|