https://ac.nowcoder.com/acm/contest/5671/H
解析:
表示
位数十进制和为
的方案数
表示被限制(前面都到达上限,即第1位需要小于等于对应位置数字)的
位数十进制和为
的方案数
表示
位数的答案(
都是
位,不受限)
dfs第p位时:
答案分为:(x代表A的位,y代表B的位,K表示这一位后面的数的长度,h表示当前位的数字,inf上限为接下来数的最大值=9K)
- 当前位
,且
这个式子自己拆开后发现很多部分是重复的,最后每一位的处理时间为 - 当前位
,且
- 当前位
ans的处理和上面这个类似,limit和dp也比较简单。
代码:
/*
* Author : Jk_Chen
* Date : 2020-07-27-13.25.56
*/
#include<bits/stdc++.h>
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<int, int>
#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*/