Project Euler 725
题目
Digit sum numbers
A number where one digit is the sum of the other
digits is called a digit sum number or DS-number for short. For
example, and are DS-numbers.
We define to be the sum of
all DS-numbers of digits or
less.
You are given and
.
Find . Give your answer
modulo .
解决方案
令 一个数如果是 DS 数,那么它的数位和是最大数位的 倍。这不难想到使用动态规划来做。
本题的动态规划过程考虑使用 “我为人人” 的方法,因为本质上都是对当前状态的所有数都添加一个新的数位 ,从而到达下一个状态。
令状态 表示当前有多少个 位有前导 0 的数,其中数位之和为 ,并且这 个数位中最大数位为
不难知道,对于初值 ,都有
考虑对 中的所有数后面都拼接一个新的数位 ,那么可以进行转移:
添加一个数位 后,那么数位和就变成了 ,最大数位也变成了
令状态 表示 位有前导 0 并满足以下条件的所有数之和:数位之和为 ,并且这 个数位中最大数位为
同样不难知道,对于初值 ,都有
考虑对 中的所有数后面都拼接一个新的数位 ,那么可以进行转移:
添加一个数位 后,相当于将 中的所有数都乘 ,并且每一个数都多了一个数位 ,一共有 个。
那么,题目最终所需要求的答案为:
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <bits/stdc++.h> typedef long long ll; using namespace std; const int N=2020; const int B=9,D=2*B; ll mod=1e16; ll c[N+1][D+1][B+1],s[N+1][D+1][B+1]; void add(ll &x,ll y){ x=(x+y)%mod; } int main(){ for(int j=0;j<=B;j++){ c[1][j][j]=1; s[1][j][j]=j; } for(int i=1;i<N;i++) for(int t=0;t<=D;t++) for(int m=0;m<=B;m++) for(int d=0;d<=B&&t+d<=D;d++){ add(c[i+1][t+d][max(d,m)],c[i][t][m]); add(s[i+1][t+d][max(d,m)],s[i][t][m]*10+c[i][t][m]*d); } ll ans=0; for(int j=0;j<=B;j++) add(ans,s[N][j+j][j]); printf("%lld\n",ans); }
|