题目链接:https://ac.nowcoder.com/acm/contest/5671/H
题意:…
解题思路:利用数位DP,
dp[pos][sum][limita][limitb][limit]
pos当前搜索位置 sum当前A与B数位差 limita A是否为上界情况 limitb B是否为上界情况 limit A小于或等于B
因为N最大取十进制100位,所以数位差绝对值最大值小于1000,所以以base=1000为数位差起点,从最高位往后进行数位dp+记忆化
注意一下dp转移和条件的讨论即可
#include<iostream>
#include<cstdio>
#include<vector>
#include<string.h>
#include<string>
using namespace std;
const int mod=1e9+7;
#define ll long long
#define base 1000 //以1000为起点
int n;
string num;
ll dp[105][2050][2][2][2];
ll dfs(int pos,int sum,int limita,int limitb,int limit){
//pos当前搜索位置 sum当前A与B数位差 limita A是否为上界情况 limitb B是否为上界情况 limit A小于或等于B
if(pos>=n)
return sum>base;
if(dp[pos][sum][limita][limitb][limit]!=-1){
return dp[pos][sum][limita][limitb][limit];
}
int up1=limita? (num[pos]-'0'):9;
int up2=limitb? (num[pos]-'0'):9;
ll res=0;
for(int i=0;i<=up1;i++){
for(int j=0;j<=up2;j++){
if(!limit&&i>j) //A本来=B且当前选择数i>j
continue;
res+=dfs(pos+1,sum+i-j,limita&&(i==up1),limitb&&(j==up2),(limit||i<j));
res%=mod;
}
}
return dp[pos][sum][limita][limitb][limit]=res;
}
int main(){
memset(dp,-1,sizeof(dp));
cin>>num;
n=num.size();
cout<<dfs(0,base,1,1,0)<<endl;
return 0;
}