链接:https://ac.nowcoder.com/acm/contest/5671/H
题意:
定义了一个运算S(),S(A)表示A这个数的所有位数上的数之和。然后给了一个很大的数(n<=10100),让我们找,A<B,并且
S
(
A
)
>
S
(
B
)
S(A)>S(B)
S(A)>S(B)的个数。
思路:
这题用数位dp还是很明显的。
我们定义dp[105][2000][2][2]:
分别表示当前第几位,
S
(
A
)
−
S
(
B
)
S(A)-S(B)
S(A)−S(B),B当前是否为上限,A当前是否为上限(这里A的上限是B,因为A<B)
然后就是数位DP的经典套路了(记忆化搜索)。
AC:
/*
* @沉着,冷静!: 噗,这你都信!
* @LastEditors: HANGNAG
* @LastEditTime: 2020-08-03 09:59:21
* @FilePath: \ACM_vscode\牛客多校\niuke.cpp
*/
#include<algorithm>
#include<string.h>
#include<iostream>
#include<stdio.h>
#include<string>
#include<math.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;
char a[105];
LL dp[105][2005][2][2];
int n;
LL dfs(int pos,int sum,int limit1,int limit2)
{
LL ans = 0;
if(pos>=n)
{
return sum > 1000;
}
if(dp[pos][sum][limit1][limit2]!=-1)
{
return dp[pos][sum][limit1][limit2];
}
int up1 = limit1 ? a[pos] - '0' : 9;
for (int i = 0; i <= up1;i++)
{
int up2 = limit2 ? i : 9;
for (int j = 0; j <= up2;j++)
{
ans += dfs(pos + 1, sum + j - i, limit1 && i == a[pos] - '0', limit2 && j == i)%mod;
}
}
ans %= mod;
return dp[pos][sum][limit1][limit2] = ans;
}
int main()
{
scanf("%s", a);
n = strlen(a);
memset(dp, -1, sizeof(dp));
printf("%lld\n", dfs(0, 1000, 1, 1)%mod);
return 0;
}