zoukankan      html  css  js  c++  java
  • 【CodeForces 520E】Pluses everywhere

    n个数里插入k个+号,所有式子的和是多少(取模1000000007) (0 ≤ k < n ≤ 105)

    分析

    1.求答案,考虑每个数作为i位数(可为答案贡献10的i-1次方,个位i=1,十位i=2,...,最多n-k位):

    那么它及后面 共i个数 之间不能有加号。

    且只有前n-i+1个数可以作为i位,如果是an-i+1作为i位,那么后面都不能有加号,k个加号在a1到an-i+1之间,所以有C(n-i,k)次贡献(这么说怪怪的→_←),就是几种情况。

    a1 a2 a3 ... an-i+1 ... an

    如果是a1、a2、...an-i作为i位,比如a1,那就是ai和ai+1之间用掉一个加号,其它加号ai+1的后面n-1-i个间隔里。

    a1 a2 a3 ... a+ ai+1 ...  an

    再比如a2,剩下k-1个加号在ai+2的后面及a1和a2之间 n-1-i个间隔里。

    a1 a2 a3 ... ai+1 + ai+2 ...  an

    所以他们都做了C(n-i-1,k-1)次贡献。

    于是就有ans=∑(i=1到n-k)[(a1+a2+...an-i)*C(n-i-1,k-1)+an-i+1*C(n-i,k)]%M。

    s[i]为前缀和,ans=∑(i=1到n-k)[s[n-i]*C(n-i-1,k-1)+an-i+1*C(n-i,k)]%M。

    2.组合数取模

    由费马小定理,当a和p互质时:ap-1≡1 mod p 可得 a*ap-2≡1 mod p,ap-2和a互为逆元。

    a/b mod p=a*b-1 mod p 也就是求除数的逆元。

    C(a,b)=a!/[b!*(a-b)!]

    所以先求出所有1到n的阶乘,和它的逆。

    代码

    #include<cstdio>
    #define M 1000000007
    #define N 100005
    #define ll long long
    
    int n,k;
    char d[N];
    ll s[N],fac[N],inv_fac[N];
    ll inv(ll a)
    {
        ll b=M-2;
        ll ans=1;
        while(b)
        {
            if(b&1) ans=ans*a%M;
            a=a*a%M;
            b>>=1;
        }
        return ans;
    }
    void init()
    {
    //初始化fac[i]i的阶乘,inv_fac[i] i的阶乘的逆元
        fac[0]=1;
        for(int i=1; i<=n; i++)
        {
            fac[i]=fac[i-1]*i;
            if(fac[i]>=M) fac[i]%=M;
        }
        inv_fac[n]=inv(fac[n]);
        for(int i=n-1;i>=0;i--){
    
    //乘(i!的逆)==除以i!==除以(i+1)!再乘以(i+1)==乘((i+1)!的逆)再乘以i+1
            inv_fac[i]=inv_fac[i+1]*(i+1);
            if(inv_fac[i]>=M) inv_fac[i]%=M;
        }
    }
    
    ll C(ll a,ll b)
    {
        return fac[a]*inv_fac[b]%M *inv_fac[a-b]%M;
    }
    int main()
    {
        scanf("%d%d ",&n,&k);
        for(int i=1; i<=n; i++)
        {
            scanf("%c",&d[i]);
            s[i]=s[i-1]+(d[i]-'0');
        }
        init();
        ll ans=0;
        ll de=1;
        for(ll i=1; n-i>=k; i++)
        {
            ans+=(d[n-i+1]-'0')*C(n-i,k)%M*de%M;
            ans+=s[n-i]*C(n-i-1,k-1)%M*de%M;
            de*=10;
            if (de>=M) de%=M;
            if (ans>=M) ans%=M;
        }
        printf("%I64d",ans);
        return 0;
    }

      

  • 相关阅读:
    【SAS NOTE】OUTPUT
    【SAS NOTES】_NULL_
    【SAS NOTE】sas 9.2 安装
    【SAS NOTE】FREQ
    纯数学教程 Page 203 例XLI (1)
    纯数学教程 Page 203 例XLI (3)
    纯数学教程 Page 203 例XLI (2)
    Prove Cauchy's inequality by induction
    纯数学教程 Page 325 例LXVIII (15) 调和级数发散
    纯数学教程 Page 325 例LXVIII (15) 调和级数发散
  • 原文地址:https://www.cnblogs.com/flipped/p/5225864.html
Copyright © 2011-2022 走看看