题目描述
给出一个长度为 (n) 的字符串,给出一个非负整数 (k),要求给这个字符串中间添加 (k) 个$$+$’号,变成一个表
达式,比如”(1000101)”,添加两个(+)号,可以变成”(10+001+01)”,或者”(1000+1+01)”,表达式的值分别是(12) 和 (1002)。
问所有的添加加号的方案的表达式的值的和是多少。
Input
两个整数 (n,k),一个字符串$ s$ ((0<=k<n<=1e5).)
Output
一个整数,模$ 1000000007$
Sample Input
3 1
108
3 2
108
Sample Output
27
9
计数(DP)
首先,看到那么大的数据范围肯定是对于每个数计算贡献。
那么我们该如何计算贡献呢?
对于题目给出的那个字符串(S),从左往右每个数字依次为(a_{n-1},a_{n-2}....a_{1},a_0).
现在,我们对于(a_t),讨论其贡献。
(a_t)右边有(t)个位置可以放置加号,同时一共有(n-1)个位置放置加号。
若(a_t)右边第一个位置放置了加号,则(a_t)被当成个位,还有(n-2)个空位,(k-1)个加号,一共有(C(k-1,n-2))种方案。
其贡献为(C(k-1,n-1)*10^{0}*a_t)。
若(a_t)右边第一个位置为空,第二个位置放置加号,则(a_t)为十位,还有(n-3)个空位,(k-1)个加号,共有(C(k-1,n-3))种方案。
贡献为(C(k-1,n-2)*10^{1}*a_t).
依次类推,
若(a_t)右边为空,则贡献为(C(k,n-t-2)*10^{t}*a_t)。
所以,(a_t)这个数的贡献为((10^{t}*C(k,n-t-2)+sum^{t}_{j=0}10^{j}*C(k-1,n-j-2))*a_t)。
于是我们可以得到第(i)个数的贡献计算公式(A_i=10^{i}*C(k,n-i-2)+sum^{i}_{j=0}10^{j}*C(k-1,n-j-2))。
最后,(Ans=sum^{n-1}_{i=0}A_i*a_i)。
代码如下
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
#define reg register
#define Raed Read
#define clr(a,b) memset(a,b,sizeof a)
#define Mod(x) (x>=mod)&&(x-=mod)
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
#pragma GCC target("avx,avx2,sse4.2")
#pragma GCC optimize(3)
inline int Read(void) {
int res=0,f=1;
char c;
while(c=getchar(),c<48||c>57)if(c=='-')f=0;
do res=(res<<3)+(res<<1)+(c^48);
while(c=getchar(),c>=48&&c<=57);
return f?res:-res;
}
template<class T>inline bool Min(T &a, T const&b) {
return a>b?a=b,1:0;
}
template<class T>inline bool Max(T &a, T const&b) {
return a<b?a=b,1:0;
}
const int N=1e5+5,M=1e6+5,mod=1e9+7;
bool MOP1;
int Fac[N],Inv[N];
inline int Pow(int x) {
int res=1,y=mod-2;
while(y) {
if(y&1)res=(res*x)%mod;
x=(x*x)%mod,y>>=1;
}
return res;
}
inline int C(int x,int y) {
if(!x)return 1;
return (Fac[y]*((Inv[x]*Inv[y-x])%mod))%mod;
}
int A[N],Pow_10[N];
char S[N];
bool MOP2;
inline void _main() {
int n=Read(),k=Read(),Ans=0,tot=0;
scanf("%s",S),Fac[0]=Pow_10[0]=Inv[0]=1;
if(!k) {
int Ans=0;
ret(i,0,n)Ans=(Ans*10+(S[i]^48))%mod;
printf("%lld
",Ans);
return;
}
rep(i,1,n) {
Fac[i]=(Fac[i-1]*i)%mod;
Pow_10[i]=(Pow_10[i-1]*10)%mod;
Inv[i]=Pow(Fac[i]);
}
A[0]=C(k-1,n-2);
int P=n-k-1;
rep(i,0,P)A[i]=(A[i-1]+Pow_10[i]*C(k-1,n-i-2))%mod;
rep(i,P+1,n)A[i]=A[i-1];
rep(i,0,P)A[i]=(A[i]+Pow_10[i]*C(k,n-i-2));
ret(i,0,n)Ans=(Ans+(S[i]^48)*A[n-i-1])%mod;
printf("%lld
",Ans);
}
signed main() {
_main();
return 0;
}