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

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

设 f(x) = 1^k + 2^k + ... + n^k

则 f(x) - f(x-1) = x^k

因为差值是 k 次的,所以 f 的次数应该是 k+1;

算出 k+2 个值就可以用拉格朗日插值求解了;

但是 k^2 会 T;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=1e6+5,mod=1e9+7;
int n,k,f[xn];
int pw(ll a,int b)
{
  ll ret=1;
  for(;b;b>>=1,a=(a*a)%mod)
    if(b&1)ret=(ret*a)%mod;
  return ret;
}
int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;}
int main()
{
  scanf("%d%d",&n,&k);
  for(int i=1;i<=k+2;i++)f[i]=upt(f[i-1]+pw(i,k));//!k+1
  int sum=0;
  for(int i=1;i<=k+2;i++)
    {
      ll s1=1,s2=1;
      for(int j=1;j<=k+2;j++)
    {
      if(i==j)continue;
      s1=s1*(n-j)%mod;
      s2=s2*(i-j)%mod;
    }
      sum=(sum+s1*pw(s2,mod-2)%mod*f[i])%mod;
    }
  printf("%d
",upt(sum));
  return 0;
}
TLE

由于 x 都是连续的,所以可以直接预处理阶乘;

分母部分的阶乘要跳过0,比较麻烦...一开始准备先算一个值,然后每次修改,但是失败了...

于是参考了一下 TJ,原来可以分正负两部分计算!

分子万一乘到0怎么办?先特判一下 n<=k+2 即可;

别忘了阶乘数组是 ll 或局部开 ll !

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=1e6+5,mod=1e9+7;
int n,k,f[xn];
ll fac[xn];//ll
int pw(ll a,int b)
{
  ll ret=1;
  for(;b;b>>=1,a=(a*a)%mod)
    if(b&1)ret=(ret*a)%mod;
  return ret;
}
int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;}
ll get(int i)
{
  if(i==k+2)return fac[i-1];
  return fac[i-1]*fac[k+2-i]%mod;
}
int main()
{
  scanf("%d%d",&n,&k);
  for(int i=1;i<=k+2;i++)f[i]=upt(f[i-1]+pw(i,k));//!k+1
  if(n<=k+2){printf("%d
",f[n]); return 0;}//!!
  int sum=0; ll s1=1; fac[0]=1;
  for(int i=1;i<=k+2;i++)fac[i]=fac[i-1]*i%mod;
  for(int i=1;i<=k+2;i++)s1=s1*(n-i)%mod;
  //for(int i=2;i<=k+2;i++)s2=s2*(1-i)%mod;
  for(int i=1;i<=k+2;i++)
    {
      ll t1=s1*pw(n-i,mod-2)%mod;
      ll s2=pw(get(i),mod-2); 
      if((k+2-i)%2)s2=-s2;
      //if(i>1)s2=s2*pw(upt(i-1-k-2),mod-2)%mod*(i-1)%mod;
      sum=(sum+t1*s2%mod*f[i])%mod;
    }
  printf("%d
",upt(sum));
  return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/10008776.html