题:https://ac.nowcoder.com/acm/contest/5671/H
题意:定义S(x)为x作为十进制的各个位数之和,问1~n中多少点对满足S(A)>S(B) (0<=A<=B<=N)(1<=N<=10^100);
分析:字符串范围,考虑数位dp,dp[i][j][limit1][limit2][statue],代表枚举到最高位为i,俩者数码和之差为j,A和N的关系为limit1,B和N的关系为limit2,A和B的大小关系为statue时的对数。
复杂度:O(len2103)
#include<bits/stdc++.h> using namespace std; #define pb push_back #define MP make_pair typedef long long ll; const int mod=1e9+7; const int M=102; const int inf=0x3f3f3f3f; const ll INF=1e18; ll dp[M][2002][3][3][3]; int a[M]; char s[M]; ll dfs(int pos,int dis,int limit1,int limit2,int statue){ if(pos==-1) return dis>0; if(~dp[pos][dis+1000][limit1][limit2][statue]) return dp[pos][dis+1000][limit1][limit2][statue]; int up1=(limit1?a[pos]:9); int up2=(limit2?a[pos]:9); ll ans=0; for(int i=0;i<=up1;i++){ for(int j=(statue?i:0);j<=up2;j++) ans=(ans+dfs(pos-1,dis+i-j,limit1&&(i==a[pos]),limit2&&(j==a[pos]),statue&&(i==j)))%mod; } return dp[pos][dis+1000][limit1][limit2][statue]=ans%mod; } int main(){ memset(dp,-1,sizeof(dp)); scanf("%s",s); int len=strlen(s); for(int i=0;i<len;i++) a[i]=s[len-1-i]-'0'; printf("%lld ",dfs(len-1,0,1,1,1)); return 0; }