CodeForces 521C Pluses everywhere :n位的整数放k个分隔符,所有方案能得到的数和 :组合数/数学思维/逆元

很末尾到首开始看每一位对总和的贡献=

倒数第一位:贡献了C(n-1,k)次个位数

倒数第二位:贡献了C(n-2,k-1)次个位数,C(n-2,k)次十位数

倒数第三位:贡献了C(n-2,k-1)次个位数,C(n-3,k-1)次十位数,C(n-3,k)次

倒数第四位:贡献了C(n-2,k-1)次个位数,C(n-3,k-1)次十位数,C(n-4,k-1)次百位数,C(n-4,k)次千位数

==

其实每位数贡献很明显,不难想到预处理出C(x,k-1)和C(x,k)然后利用前缀和思想统计即可=

哈哈,偷来了一个比大白书好看的exgcd求逆元模板==

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 #define MOD 1000000007
 6 #define LL long long
 7 #define ll I64
 8 LL s[100005],c1[100005],c2[100005];
 9 LL inv(LL a)
10 {
11   LL b=MOD,b0=b,t,q,x0=0,x1=1;
12   if (b==1) return 1;
13   while (a>1)
14   {
15     q=a/b;
16     t=b,b=a%b,a=t;
17     t=x0,x0=x1-q*x0,x1=t;
18   }
19   if (x1<0) x1+=b0;
20   return x1;
21 }
22 int main()
23 {
24   LL n,k,i,ans,tmp,shi,j;
25   scanf("%lld%lld",&n,&k);
26   for (i=1;i<=n;i++) scanf("%1lld",&s[i]);
27   if (k==0){
28     ans=0;
29     for (i=1;i<=n;i++) ans=(ans*10+s[i])%MOD;
30     printf("%lld\n",ans); return 0;
31   }
32   c1[k-1]=c2[k]=1;
33   for (i=k;i<=n;i++) 
34     c1[i]=(c1[i-1]*i)%MOD*inv(i-k+1)%MOD;
35   for (i=k+1;i<=n;i++) 
36     c2[i]=(c2[i-1]*i)%MOD*inv(i-k)%MOD;
37   ans=tmp=0; shi=j=1;
38   for (i=n;i>=1;i--)
39   {
40     if (i==n) ans=(ans+s[i]*c2[n-1])%MOD;
41     else {
42       j++;
43       tmp=(tmp+c1[n-j]*shi)%MOD;
44       shi=shi*10%MOD;
45       ans=ans+(tmp+c2[n-j]*shi%MOD)*s[i]%MOD;
46     }
47   }
48   printf("%lld\n",ans%MOD);
49   return 0;
50 }
View Code

题目链接:http://codeforces.com/contest/521/problem/C

posted on 2015-03-02 23:04  xiao_xin  阅读(213)  评论(0编辑  收藏  举报

导航