题目描述
设S(x)表示十进制表示下x的每位数字之和,当S(A)>S(B)时,(A,B)表示一个和谐对。
给定N,求满足 的和谐对(A,B)的数量,答案对 取模。
输入描述
- 只有一行整数N( )。
输出描述
- 输出一个整数作为答案。
样例
- 输入
100 - 输出
967
题解思路
首先最吸引人眼球的应该是N的取值范围了,一看就会让人联想到高精度。
想什么呢
跟数字有关,当然是数位dp而非高精。
作为数位DP,自然就有暴力枚举记忆化。
根据题意,可以定义dp数组的维度[pos][A][B][l1][l2]。但用头发想想就知道,这么sao6的数组显然是开不下的。所以需要精简一下,把第二第三维度压缩为一个维度[sum]。
- pos指位置;
- sum指当前的A与B之和(但要小心,可能是负数);
- l1限制 ;
- l2限制 .
行,DFS细节详见代码。
参考代码
#include <bits/stdc++.h> using namespace std; const int mod=1e9+7; const int MAXN=110; int n,a[MAXN],dp[MAXN][MAXN*20][2][2]; char s[MAXN]; int dfs(int x,int d,int lim1,int lim2) { if(!x) return d>1000; if(~dp[x][d][lim1][lim2]) return dp[x][d][lim1][lim2]; int ret=0,lim=lim1?a[x]:9; for(int i=0;i<=lim;i++) for(int j=0;j<=(lim2?i:9);j++) ret=(ret+dfs(x-1,d+j-i,lim1&(a[x]==i),lim2&(i==j)))%mod; return dp[x][d][lim1][lim2]=ret; } int main() { memset(dp,-1,sizeof(dp)); scanf("%s",s); int len=strlen(s); for(int i=0;i<len;i++) a[len-i]=s[i]-'0'; printf("%d",dfs(len,1000,1,1)%mod); }