CF 622F The Sum of the k-th Powers——拉格朗日插值

题目:http://codeforces.com/problemset/problem/622/F

发现 sigma(i=1~n) i 是一个二次的多项式( (1+n)*n/2 ),sigma(i=1~n) i^2 是一个三次的多项式,所以 sigma(i=1~n) i^k 是一个k+1次的多项式。用拉格朗日插值就能做了。

注意别弄成 n^2 的。其实就是移动一个位置的时候乘一个数除以一个数,这样的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e6+5,mod=1e9+7;
int n,k,a[N],inv[N],ans;
int pw(int x,int k)
{int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret;}
void upd(int &x){x>=mod?x-=mod:0;}
int main()
{
  scanf("%d%d",&n,&k); int lm=k+2;
  if(n<=lm)
    {
      for(int i=1;i<=n;i++)a[i]=a[i-1]+pw(i,k),upd(a[i]);
      printf("%d\n",a[n]); return 0;
    }
  for(int i=1;i<=lm;i++)inv[i]=pw(i,mod-2);
  int s0=1;
  for(int i=1;i<=lm;i++)s0=(ll)s0*(n-i)%mod;
  int s1=1,fx=((lm-1)&1?-1:1);
  for(int i=2;i<=lm;i++)s1=(ll)s1*(i-1)%mod;
  a[1]=1;
  ans=(ll)s0*pw(n-1,mod-2)%mod*fx*pw(s1,mod-2)%mod*a[1]%mod;
  for(int i=2;i<=lm;i++)
    {
      a[i]=a[i-1]+pw(i,k);upd(a[i]);
      fx=-fx;
      s1=(ll)s1*(i-1)%mod*inv[lm-i+1]%mod;
      ans=(ans+(ll)s0*pw(n-i,mod-2)%mod*fx*pw(s1,mod-2)%mod*a[i])%mod;
    }
  printf("%d\n",ans<0?ans+mod:ans);
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/Narh/p/10009937.html