题目描述
设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);
}
京公网安备 11010502036488号