H-Harmony Pairs(数位dp)
题意:S(A)表示数字A的每一位数的和,S(24)=2+4=6,S(209)=2+0+9=11
求0到N中有多少对AB,使得S(A)>S(B) ,
0<=A<=B<=N<=10100
数位dp裸题,挺暴力的 dp[pos][sta][l1][l2]。
其中pos表示枚举到的下标
sta表示到pos之前AB的差值之和,为了避免出现负数,可以将其离散到999
l1表示A取数的上界 l2表示B取数的上界
sta-i+j是因为S(A)>S(B),A<=B所以sta-i+j
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#define ll long long
using namespace std;
const int INF=0x3f3f3f3f;
const double pi=acos(-1.0),eps=1e-8;
const int maxn=1e5+10;
const ll mod=1e9+7;
int dp[105][2005][2][2];
int a[105];
string b;
int dfs(int pos,int sta,bool limit1,bool limit2)
{
if(pos==-1)//枚举到末尾
return sta>999;
if(dp[pos][sta][limit1][limit2]!=-1)
return dp[pos][sta][limit1][limit2];
int up=limit1?a[pos]:9;
int ans=0;
for(int i=0; i<=up; i++)//枚举B
{
int up2=limit2?i:9;
for(int j=0; j<=up2; j++)//枚举A
{
ans+=dfs(pos-1,sta+j-i,limit1&&(i==a[pos]),limit2&&(j==up2));
ans%=mod;
}
}
dp[pos][sta][limit1][limit2]=ans;
return ans;
}
int solve(string x)
{
int pos=0;
for(int i=b.size()-1; i>=0; i--)
{
a[pos++]=b[i]-'0';
}
return dfs(pos-1,999,true,true);
}
int main()
{
memset(dp,-1,sizeof dp);
cin>>b;
printf("%d\n",solve(b));
return 0;
}