HDU-4389 X mod f(x) && 2018上海大都会邀请赛J 数位dp
Posted qaqorz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU-4389 X mod f(x) && 2018上海大都会邀请赛J 数位dp相关的知识,希望对你有一定的参考价值。
题意:给出区间【L,R】,求其中有多少个数满足自身被数位和整除
比赛出了刚好没刷的原题系列= =
思路:枚举的过程中很好记录数位和,但是一个数字可以很大(1e9、1e12),不能加到状态里
既然相对很小的量是数位和,考虑枚举最终的数位和作为模数,用它来模过程中得到的数字num,这样num就可以加入状态了
最后只要枚举到的数位和确实是这个模数,就是一个可行解,明确状态之后套模板即可
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int a[10], dp[10][90][90][90]; 7 8 int dfs(int pos, int sum, int mod, int res, bool lim){ 9 if (pos == -1) return (sum == 0 && res == mod); 10 if (!lim && dp[pos][sum][mod][res] != -1) return dp[pos][sum][mod][res]; 11 int r = lim ? a[pos] : 9; 12 int ans = 0; 13 for (int i = 0; i <= r; i++){ 14 ans += dfs(pos-1, (sum*10+i)%mod, mod, res+i, lim && i == a[pos]); 15 } 16 if (!lim) dp[pos][sum][mod][res] = ans; 17 return ans; 18 } 19 20 int solve(int x){ 21 int pos = 0; 22 while (x){ 23 a[pos++] = x%10; 24 x /= 10; 25 } 26 int ans = 0; 27 for (int i = 1; i <= 81; i++) 28 ans += dfs(pos-1, 0, i, 0, 1); 29 return ans; 30 } 31 32 int main(){ 33 int t, a, b, kase = 0; 34 scanf("%d", &t); 35 memset(dp, -1, sizeof dp); 36 while (t--){ 37 scanf("%d%d", &a, &b); 38 printf("Case %d: %d ", ++kase, solve(b)-solve(a-1)); 39 } 40 return 0; 41 }
以上是关于HDU-4389 X mod f(x) && 2018上海大都会邀请赛J 数位dp的主要内容,如果未能解决你的问题,请参考以下文章