https://ac.nowcoder.com/acm/contest/5671/H
解析:
d p [ i ] [ j ] dp[i][j] dp[i][j]表示 i i i位数十进制和为 j j j的方案数
l i m i t [ i ] [ j ] limit[i][j] limit[i][j]表示被限制(前面都到达上限,即第1位需要小于等于对应位置数字)的 i i i位数十进制和为 j j j的方案数
s u m [ i ] [ j ] = ∑ k = 1 j d p [ i ] [ k ] sum[i][j]=\sum_{k=1}^jdp[i][k] sum[i][j]=∑k=1jdp[i][k]
a n s [ i ] ans[i] ans[i]表示 i i i位数的答案( A , B A,B A,B都是 i i i位,不受限)
dfs第p位时:
答案分为:(x代表A的位,y代表B的位,K表示这一位后面的数的长度,h表示当前位的数字,inf上限为接下来数的最大值=9K)
ans的处理和上面这个类似,limit和dp也比较简单。
代码:
/*
* Author : Jk_Chen
* Date : 2020-07-27-13.25.56
*/
#include
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
int len;
char x[109];
void Add(LL &a,LL b){
a=a+b;
while(a>=mod)a-=mod;
}
LL mxbit[109];
LL dp[109][909]; // mx=900
LL sumdp[109][909];
LL limit[109][999];
LL sumlimit[109][999];
LL ans[109];
void initdfs(int p){
if(p==len){
rep(i,0,x[len])
limit[1][i]=1;
return;
}
initdfs(p+1);
int res=len-p+1;
rep(i,0,x[p]-1){
rep(j,0,mxbit[res-1]){
limit[res][j+i]=(limit[res][j+i]+dp[res-1][j])%mod;
}
}
rep(j,0,mxbit[res-1]){
limit[res][j+x[p]]=(limit[res][j+x[p]]+limit[res-1][j])%mod;
}
}
void init(){
/// dp
dp[0][0]=1;
rep(i,1,101){
rep(j,0,mxbit[i-1]){
rep(k,0,9){
dp[i][j+k]=(dp[i][j+k]+dp[i-1][j])%mod;
}
}
mxbit[i]=mxbit[i-1]+9;
}
/// limit
initdfs(1);
/// sum
rep(i,1,101){
sumdp[i][0]=dp[i][0];
sumlimit[i][0]=limit[i][0];
rep(j,1,mxbit[i]){
sumdp[i][j]=(sumdp[i][j-1]+dp[i][j])%mod;
}
rep(j,1,mxbit[i]){
sumlimit[i][j]=(sumlimit[i][j-1]+limit[i][j])%mod;
}
}
/// ans
ans[1]=0;
rep(res,2,101){
rep(st,2,10){
LL tmp=0;
rep(i,st,mxbit[res-1]){
Add(tmp,dp[res-1][i]*sumdp[res-1][i-st]%mod);
}
Add(ans[res],tmp*(11-st)%mod);
}
Add(ans[res],10*ans[res-1]%mod);
}
}
LL Ans;
void dfs(int p){
if(p==len){
return;
}
int res=len-p+1;
Add(Ans,x[p]*ans[res-1]%mod);
if(x[p]>=2){
rep(st,2,x[p]){
LL tmp=0;
rep(i,st,mxbit[res-1]){
Add(tmp,dp[res-1][i]*sumdp[res-1][i-st]%mod);
}
Add(Ans,tmp*(x[p]+1-st)%mod);
}
}
if(x[p]>=1){
rep(st,2,x[p]+1){
rep(i,st,mxbit[res-1]){
Add(Ans,dp[res-1][i]*sumlimit[res-1][i-st]%mod);
}
}
}
dfs(p+1);
}
int digit(int n){
int res=0;
while(n){
res+=n%10;
n/=10;
}
return res;
}
void getReal(int n){
int res=0;
rep(i,0,n){
rep(j,i+1,n){
if(digit(i)>digit(j))res++;
}
}
printf("real %d\n",res);
}
int main(){
#define TEST_
#ifdef TEST
int tmp=rd;
getReal(tmp);
while(tmp){
x[++len]=tmp%10;
tmp/=10;
}
reverse(x+1,x+1+len);
#else
scanf("%s",x+1);
len=strlen(x+1);
rep(i,1,len)x[i]=x[i]-'0';
#endif // TEST
init();
dfs(1);
printf("%lld\n",Ans);
return 0;
}
/// 2121
/*_________________________________________________________end*/