Codeforces 622 F. The Sum of the k-th Powers

题目:点击打开链接
题意:求sigma(i : 1 to n)i^k。 

分析:

做这个题之前需要知道一些知识:

拉格朗日插值:n-1次多项式可以用n个点唯一确定,插值公式是:

Codeforces 622F (拉格朗日插值 费马小定理)_第1张图片

对于这道题可以发现对于每一个k次幂的积都可以用一个k+1次幂的多项式表示,于是我们可以构造出k+2个点来拟合这个多项式.拉格朗日插值公式在这里就是:

我们需要求的就是F(n),带入以后就是:

Codeforces 622F (拉格朗日插值 费马小定理)_第2张图片

然后就是简单的预处理和取模了,仔细点就可以了

代码:

#pragma comment(linker, "/STACK:102400000,102400000")///手动扩栈
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<bitset>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<map>
using namespace std;
#define debug test
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define MOD 1000000007
#define PI acos(-1.0)
const int N = 1e6+10;

ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

ll n,k,ans,fac[N],y[N];

ll qp(ll a,ll b) {
    ll s=1;
    while(b) {
        if(b&1) s=s*a%MOD;
        a=a*a%MOD,b>>=1;
    }
    return s;
}

void init() {
    fac[0]=fac[1]=1,y[1]=1;
    for(int i=2;i<N;i++) fac[i]=fac[i-1]*i%MOD;
    for(int i=2;i<N;i++) y[i]=(y[i-1]+qp(i,k))%MOD;
}

void sv() {
    if(k==0) {
        cout<<n<<endl;
        return ;
    }
    if(n<=k+2) {
        cout<<y[n]<<endl;
        return ;
    }
    ll sum=1,sig;
    for (ll i = n-k-2; i <= n-1; i++) sum = sum*i%MOD;
    for(ll i=1;i<=k+2;i++) {
        ll fz=sum*qp(n-i,MOD-2)%MOD;
        ll fm=qp(fac[i-1]*fac[k+2-i]%MOD,MOD-2);
        if((k+2-i)%2==0) sig=1;
        else sig=-1;
        ans+=sig*y[i]*fz%MOD*fm%MOD;
        ans%=MOD;
    }
    cout<<(ans%MOD+MOD)%MOD<<endl;
}

int main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>k;
    init();
    sv();
    return 0;
}

参考博客:http://www.it610.com/article/5412064.htm

猜你喜欢

转载自blog.csdn.net/tianwei0822/article/details/81153921