自然冪數和(拉格朗日插值)
阿新 • • 發佈:2020-07-17
求 $\sum_{i=1}^{n} i^k$.
這是一個關於 $n$ 的 $k+1$ 次多項式.
所以可以取 $k+2$ 個點帶進去,然後用拉格朗日插值法來求值.
具體,$f(k)=\sum_{i=1}^{n} y_{i} \prod_{}^{i \neq j}\frac{k-x_{j}}{x_{i}-x_{j}}$
由於點可以做到取 $x$ 連續的,所以提前預處理字首/字尾積極可以做到 $O(n \log n)$.
code:
#include <cstdio> #include <vector> #include <cstring> #include <algorithm> #define N 1000009 #define ll long long #define mod 1000000007 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int f[N]; int ifac[N],fac[N],pre[N],suf[N],inv[N],n,K; int qpow(int x,int y) { int tmp=1; for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) tmp=(ll)tmp*x%mod; return tmp; } int INV(int x) { return qpow(x,mod-2); } void init() { ifac[0]=fac[0]=inv[1]=1; for(int i=2;i<N;++i) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; inv[0]=1; for(int i=1;i<N;++i) { fac[i]=(ll)fac[i-1]*i%mod; ifac[i]=(ll)ifac[i-1]*inv[i]%mod; } pre[0]=1,suf[n+1]=1; for(int i=1;i<=n;++i) pre[i]=(ll)pre[i-1]*(K-i+mod)%mod; for(int i=n;i>=1;--i) suf[i]=(ll)suf[i+1]*(K-i+mod)%mod; } int sol() { int ans=0; for(int i=1;i<=n;++i) { int a1=(ll)ifac[i-1]*ifac[n-i]%mod; if((n-i)&1) a1=(ll)a1*(mod-1)%mod; int a2=(ll)pre[i-1]*suf[i+1]%mod; (ans+=(ll)f[i]*a1%mod*a2%mod)%=mod; } return ans; } int main() { // setIO("input"); scanf("%d%d",&K,&n),n+=2; init(); for(int i=1;i<=n;++i) { f[i]=(ll)(f[i-1]+qpow(i,n-2))%mod; } printf("%d\n",sol()); return 0; }