Educational DP Contest S-Digit Sum(数位dp)

Posted meanttobe

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational DP Contest S-Digit Sum(数位dp)相关的知识,希望对你有一定的参考价值。

S - Digit Sum

原题链接:https://atcoder.jp/contests/dp/tasks/dp_s

题目大意:

给一个n,求从1到n的数中,所有位上的数字之和能被m整除的个数。

解题思路:

数位$dp$,建一个三维数组,$dp[i][j][k]$,其中,$i$代表第几位,j代表位数前i位位数之和对$m$取余的结果,$k$代表前i位是否已经是最大的数,如果已经是最大的,那$i+1$位就从$0$遍历到$n[i+1]$,否则就遍历到9。然后记忆化搜索。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define debug(a) cout<<#a<<":"<<a<<endl;
 5 const ll INF=0x3f3f3f3f;
 6 const ll N=1e6+7;
 7 const ll mod=1e9+7;
 8 ll maxn,minn;
 9 ll T,n,m,k;
10 string s;
11 ll arr[N];
12 ll dp[10010][110][2];
13 
14 ll dfs(ll a,ll b,ll c){
15     ll d,ans=0,bb;
16     if(dp[a][b][c]!=-1){
17         return dp[a][b][c];
18     }
19     if(a==n+1){
20         if(b==0){
21             return dp[a][b][c]=1;
22         }
23         else{
24             return dp[a][b][c]=0;
25         }
26     }
27     if(c==1){
28         d=arr[a];
29     }
30     else{
31         d=9;
32     }
33     for(ll i=0;i<=d;i++){
34         bb=(b+i)%k;
35         dp[a+1][bb][c&(i==d)]=dfs(a+1,bb,c&(i==d));
36         ans=(ans+dp[a+1][bb][c&(i==d)])%mod;
37     }
38     return dp[a][b][c]=ans;
39 }
40 
41 int main(){
42     cin>>s>>k;
43     n=s.size();
44     for(ll i=1;i<=n;i++){
45         arr[i]=s[i-1]-0;
46     }
47     memset(dp,-1,sizeof(dp));
48     
49     printf("%lld
",(dfs(1,0,1)-1+mod)%mod);
50
51     return 0;
52 }

 

以上是关于Educational DP Contest S-Digit Sum(数位dp)的主要内容,如果未能解决你的问题,请参考以下文章

Educational DP Contest

Educational Codeforces Round 59 (Rated for Div. 2) E 区间dp + 状态定义

Educational Codeforces Round 63-D(基础DP)

Educational Codeforces Round 76 (Rated for Div. 2) E. The Contest

Educational Codeforces Round 80 C. Two Arrays

Educational Codeforces Round 73 (Rated for Div. 2) D. Make The Fence Great Again(DP)