题意:给定长度为n的数字串,在空隙添上k个+号,可以得到一个式子,求出插入k个+号可以得到的所有式子的计算结果之和
公式题:
代码中a[i]与上面公式中是反的,代码中a[i]是从左往右的。
在对M=10^9 +7 取模的情况下,计算组合数C(n,k)可以预处理fac[i](i 的阶乘)和 revfac[i](i 在模M下的乘法逆)
然后线性递推一下系数数组,最后求和。
要说明的是,代码中的C(n,k)没有处理n<0而k>=0的情况(这时不一定为0,而代码中直接令它为0)
所以上述公式直接使用会有误差,于是代码中特判了k=0的情况,避免组合数出问题。
代码:
#include <iostream> #include <cstdio> #include <cmath> #define maxn 100007 #define M 1000000007 #define LL long long using namespace std; LL fac[maxn]; LL ten[maxn]; LL revfac[maxn]; LL QuickPower(LL a,LL k){//快速幂 LL ANS=1; while(k){ if(k&1) ANS=(ANS*a)%M; k>>=1; a=(a*a)%M; } return ANS; } LL C(LL n,LL k){//组合数 if(k<0||k>n ||n <0) return 0; LL ANS=fac[n]; ANS=(ANS*revfac[k])%M; ANS=(ANS*revfac[n-k])%M; return ANS; } void Init(){//初始化阶乘fac数组以及阶乘乘法逆revfac数组 ten[0]=fac[0]=revfac[0]=1; for(int i=1;i<maxn;++i){ fac[i]=(i*fac[i-1])%M; revfac[i]=QuickPower(fac[i],M-2); ten[i]=(10*ten[i-1])%M; } } int n,k; char str[maxn]; LL Coef[maxn]; int main(void) { Init(); while(~scanf("%d%d",&n,&k)){ scanf("%s",str); if(k==0){ LL ANS=0; for(int i=0;i<n;++i) ANS=(ANS+ten[i]*(str[n-i-1]-'0'))% M; printf("%d\n",(int)ANS); continue; } int D=n-k-1;//计算系数 Coef[0]=C(n-2,k-1); for(int i=1;i<=D;++i) Coef[i]=(Coef[i-1]+ten[i]*C(n-i-2,k-1))% M; for(int i=D+1;i<n;++i) Coef[i]=Coef[i-1]; for(int i=0;i<=D;++i) Coef[i]=(Coef[i]+ten[i]*C(n-i-2,k))% M; LL ANS=0;//计算最终答案 for(int i=0;i<n;++i){ ANS=(ANS+Coef[n-i-1]*(str[i]-'0'))% M; } printf("%d\n",(int)ANS); } return 0; }