传送门:http://codeforces.com/problemset/problem/520/E
有一串n个数,在n个数中插入k个加号,拆成k+1个数,求着n*(k+1)的数的和是多少
当然,暴力枚举是不可以的hhh,所以要考虑别的思路
对于一个数12345相当于1*10^4+2*10^3+3*10^1+4*10^0
所以只要考虑每一个数在每一位上的次数
从低到高分别为1~n位
则每一位可以充当的是第1~i-1位,再通过组合数计算总数,当然不合法的情况用组合数为0干掉就好
然后公式的话
就酱
然后,会遇到两个问题,一个是组合数取模
具体方法以后再放链接
二是优化的问题,要预处理sigma(10^(j-1)*C(n-j-1,k-1))否则就是O(n^2)的算法,预处理的话是O(n)的
代码如下:
#include<cstdio>
#include<cstring>
#define MOD 1000000007
using namespace std;
int n,k;
long long ans=0;
int s[100005];
long long t[100005];
long long fact[100005];
long long f[100005];
long long inv[100005];
long long d[100005];
char op;
void getfact()
{
fact[0]=fact[1]=inv[0]=inv[1]=f[0]=f[1]=1;
for (int i=2;i<=n;i++)
{
fact[i]=fact[i-1]*i%MOD;
f[i]=(MOD-MOD/i)*f[MOD%i]%MOD;
inv[i]=inv[i-1]*f[i]%MOD;
}
}
long long C(int n,int m)
{
if (m>n || m<0)
{
return 0;
}
return fact[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int main()
{
scanf("%d%d",&n,&k);
getchar();
t[0]=1;
for (int i=1;i<=n;i++)
{
t[i]=(t[i-1]*10)%MOD;
}
if (k)
{
for (int i=n;i;i--)
{
op=getchar();
s[i]=op-'0';
}
d[0]=0;
getfact();
for (int i=1;i<=n;i++)
{
d[i]=d[i-1]+t[i-1]*C(n-i-1,k-1);
d[i]%=MOD;
}
ans=0;
for (int i=1;i<=n;i++)
{
ans+=s[i]*((t[i-1]*C(n-i,k)%MOD+d[i-1])%MOD);
ans%=MOD;
}
}
else
{
for (int i=1;i<=n;i++)
{
op=getchar();
s[i]=op-'0';
}
ans=0;
for (int i=1;i<=n;i++)
{
ans+=s[i]*t[n-i];
ans%=MOD;
}
}
printf("%I64d\n",ans);
return 0;
}