题目链接
题目大意:
给你一个数n,问从0-n范围内,有多少对数满足a
解题思路:
这题就是裸的数位dp,可惜以前没写过求解数对的题目,太菜了,看了别人的代码,觉得还是挺好理解的 ,就是设置一个四维数组dp[][][][],第一维记录数位(每个数位dp都是),第二维记录位数和(因为有正有负,所以要向右即比0大的数偏移),第三维记录第一个数是否达到边界,第四维记录第二个数是否达到边缘
代码:
#include<bits/stdc++.h>
#define pb emplace_back
using namespace std;
const int maxn = 1e3;
const int mod = 1e9+7;
typedef long long ll;
typedef pair<int,int> Pii;
template <typename T>inline void read(T& t){
char c=getchar();t=0;
int f=1;
while(!isdigit(c)){
if(c=='-')f=-1;
c=getchar();
}
while(isdigit(c))t=t*10+c-48,c=getchar();
t=f*t;
}
template <typename T,typename... Args> inline void read(T& t,Args&... args){
read(t);read(args...);
}
string str;
ll dp[105][1810][2][2];
ll dfs(int pos,int sum,bool limita,bool limitb){
if(pos<0){
return sum>905;
}
if(dp[pos][sum][limita][limitb]!=-1){
return dp[pos][sum][limita][limitb];
}
int upa=limita?str[pos]-'0':9;
ll tmp=0;
for(int i=0;i<=upa;i++){
int upb=limitb?i:9;
for(int j=0;j<=upb;j++){
tmp+=dfs(pos-1,sum+j-i,limita&&i==upa,limitb&&j==upb);
tmp%=mod;
}
}
return dp[pos][sum][limita][limitb]=tmp;
}
int main(){
memset(dp,-1,sizeof(dp));
cin>>str;
int r=str.size()-1;
reverse(str.begin(),str.end());
cout<<dfs(r,905,true,true)<<endl;
return 0;
}