zoukankan      html  css  js  c++  java
  • 有关1~n的m次方和的快速计算;

    首先,我们可以知道,这个$sum_{i=1}^{n}i^{m}$的通项公式是一个m+1次的多项式;

    下面就对其正确性进行论证;

    我们设多项式:$f(x)=sum_{i=0}^{n}u_{i}x^{i}$

    设对于数列a{ },a[x]=f(x);

    假如b{x}=a[x+1]-a[x]; 那么显然:$b[x]=sum_{i=0}^{n}u_{i}(x+1)^{i}-sum_{i=0}^{n}u_{i}x^{i}$

    对于上面的式子,加入我们只考虑$x^{v}$,显然只有i=v的时候才又可能出现$x^{v}这一项$

    那么式子可以看成:$b[x]=u_{v}(x+1)^{v}-u_{v}x^{v}$

    由于我们只考虑$x^{v}$,所以$(x+1)^{v}$完全可以看成$x^{v}$

    式子可以简化为:$b[x]=u_{v}x^{v}-u_{v}x^{v}=0$

    发现了没有发现了没有?对于一个可以用n次多项式表示通项公式的数列a,它的差分数列b中的通项公式不会出现x的n次幂,也就是说,b的通项公式是一个(n-1)次多项式!

    也就是说,做一次差分之后数列的通项公式的多项式次数会-1;

    对于$sum_{i=1}^{n}i^{m}$,原数列a{ }是:

    那么它的差分数列b{ }就是:

    即:$b[x]=x^{k}$

    嘿!b[x]这可是一个k次多项式啊!那么根据之前所推,a[x]不就是一个(k+1)次多项式吗?

    所以说,$sum_{i=1}^{n}x^{m}$的通项公式是一个(m+1)次的多项式;

    好了~完结撒花~;

    接下来的步骤就很套路了,根据拉格朗日插值的特点,我们选取任意连续的值xi,求出他们所对应的多项式的值yi,然后利用插值法O(n)的计算f(n)就好了;

    具体的求法见我的这篇博客:(传送门)

    #include <bits/stdc++.h>
    #define p 1000000007
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    #define dec(i,a,b) for(register int i=a;i>=b;i--)
    using namespace std;
    long long x[1000010],y[1000010];
    long long KSM(long long a,long long b){
        long long res=1;
        while(b){
            if(b&1) res=res*a%p;
            a=a*a%p;
            b/=2;
        }
        return res%p;
    }
    long long pre[1000010],suf[1000010],fac[1000010];
    int main()
    {
        long long n,m;
        cin>>n>>m;
        long long sum=0;
        inc(i,1,m+1){
            long long tmp=KSM(i,m);
            sum=(sum+tmp)%p;
            x[i]=i; y[i]=sum;
        }
        long long ans=0;
        pre[0]=n; fac[0]=1;
        inc(i,1,m+1) pre[i]=pre[i-1]*(n-i)%p,fac[i]=fac[i-1]*i%p;
        suf[m+1]=((n-x[m+1])%p+p)%p;
        dec(i,m,0) suf[i]=suf[i+1]*(n-i)%p;
        inc(i,0,m+1){
            long long tmp1=pre[i-1];
            long long tmp2=suf[i+1]; 
            if(i==0) tmp1=1;
            if(i==m+1) tmp2=1;
            long long tmp3=y[i]*tmp1%p*tmp2%p;
            if((m+1-i)%2==0) ans=(ans+tmp3*KSM((fac[i]*fac[m+1-i]%p),p-2)%p);
            else ans=(ans+tmp3*KSM((((-fac[i]*fac[m+1-i])%p+p)%p),p-2)%p);
        }
        
        /*    
        inc(i,0,m+1){
            long long tmp=1;
            inc(j,0,m+1){
                if(i==j) continue;
                tmp=(tmp*(n-j)%p*KSM(i-j,p-2)%p);
            }
            ans=(ans+y[i]*tmp%p)%p;
        }
        */
        cout<<(ans%p+p)%p;
    }

    然后可以水掉这一道题 :[TJOI2018]教科书般的亵渎

    小豆喜欢玩游戏,现在他在玩一个游戏遇到这样的场面,每个怪的血量为a_iai,且每个怪物血量均不相同,小豆手里有无限张“亵渎”。亵渎的效果是对所有的怪造成11点伤害,如果有怪死亡,则再次施放该法术。我们认为血量为00怪物死亡。

    小豆使用一张 “亵渎”会获得一定的分数,分数计算如下,在使用一张“亵渎”之后,每一个被亵渎造成伤害的怪会产生x^kxk,其中xx是造成伤害前怪的血量为xx和需要杀死所有怪物所需的“亵渎”的张数kk

    输入格式

    第一行输入一个TT(Tleq10T10),表示有多少组测试数据

    每组组测试数据第一行为nnmm,表示有当前怪物最高的血量nn,和mm种没有出现的血量

    接下来mm行,每行11个数a_iai,表示场上没有血量为a_iai的怪物

    输出格式

    一共TT行,每行一个数, 第ii行表示第ii组测试数据中小豆的最后可以获得的分数, 因为这个分数会很大需要模10^9+7109+7

    #include <bits/stdc++.h>
    #define p 1000000007
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    #define dec(i,a,b) for(register int i=a;i>=b;i--)
    using namespace std;
    long long x[1000010],y[1000010];
    long long KSM(long long a,long long b){
        long long res=1;
        while(b){
            if(b&1) res=res*a%p;
            a=a*a%p;
            b/=2;
        }
        return res%p;
    }
    long long pre[1000010],suf[1000010],fac[1000010];
    int solve(long long n,long long m)
    {
        long long sum=0;
        inc(i,1,m+1){
            long long tmp=KSM(i,m);
            sum=(sum+tmp)%p;
            x[i]=i; y[i]=sum;
        }
        pre[0]=n; fac[0]=1;
        inc(i,1,m+1) pre[i]=pre[i-1]*(n-i)%p,fac[i]=fac[i-1]*i%p;
        suf[m+1]=((n-x[m+1])%p+p)%p;
        dec(i,m,0) suf[i]=suf[i+1]*(n-i)%p;
        long long ans=0;
        inc(i,0,m+1){
            long long tmp1=pre[i-1];
            long long tmp2=suf[i+1]; 
            if(i==0) tmp1=1;
            if(i==m+1) tmp2=1;
            long long tmp3=y[i]*tmp1%p*tmp2%p;
            if((m+1-i)%2==0) ans=(ans+tmp3*KSM((fac[i]*fac[m+1-i]%p),p-2)%p);
            else ans=(ans+tmp3*KSM((((-fac[i]*fac[m+1-i])%p+p)%p),p-2)%p);
        }
        return ((ans%p)+p)%p;
    }
    long long a[100];
    int main()
    {    
        int T;
        cin>>T;
        while(T--){
            long long ans=0;
            long long tot;
            int num; scanf("%lld%d",&tot,&num);
            inc(i,1,num) scanf("%lld",&a[i]);
            sort(a+1,a+1+num);
            while(a[num]==tot){
                --num;
                --tot;
            }
            long long k=num+1;
            int now=1;
            while(now<=k){
                ans=(ans+solve(tot,k))%p;
                inc(i,now,num){
                    ans=((ans-KSM(a[i],k))+p)%p;
                }
                tot=(tot-a[now]);
                long long tmp=a[now];
                inc(i,now,num){
                    a[i]-=tmp;
                }
                ++now;
            }
            printf("%lld
    ",ans);
        }
    }
    /*
    2
    4 2
    1
    2
    10 1
    5
    
    */

    [TJOI2018]教科书般的亵渎

  • 相关阅读:
    git(1)-git关联GitHub-windows-转载
    jenkins(4)-jenkins配置邮件通知
    jenkins(3)-linux下安装jenkins(yum install方式)
    【PAT甲级】1090 Highest Price in Supply Chain (25 分)(DFS)
    【PAT甲级】1087 All Roads Lead to Rome (30 分)(MAP【int,string】,邻接表,DFS,模拟,SPFA)
    【PAT甲级】1018 Public Bike Management (30 分)(DFS,SPFA)
    Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)
    Atcoder Grand Contest 032C(欧拉回路,DFS判环)
    Educational Codeforces Round 62 (Rated for Div. 2)E(染色DP,构造,思维,组合数学)
    Atcoder Grand Contest 031C(构造,思维,异或,DFS)
  • 原文地址:https://www.cnblogs.com/kamimxr/p/12108505.html
Copyright © 2011-2022 走看看