题目:
https://codeforces.com/problemset/problem/622/F
给定 n n n, k k k,求
f ( n ) = ∑ i = 1 n i k f(n)=\sum_{i=1}^{n}i^k f(n)=i=1∑nik
1 ≤ n ≤ 1 0 9 , 0 ≤ k ≤ 1 0 6 1\le n\le10^9,0\le k\le10^6 1≤n≤109,0≤k≤106
思路:
拉格朗日插值,把 f ( 1 ) , f ( 2 ) . . . f ( k + 2 ) f(1),f(2)...f(k+2) f(1),f(2)...f(k+2)带进去,时间复杂度能降到 O ( k ) O(k) O(k)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+9;
const ll mod=1e9+7;
namespace polysum
{
const int D=1e6+9;
ll p[D],p1[D],p2[D];
ll qpow(ll a,ll b){
ll res=1;a%=mod;while(b){
if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}
void init(int n)//x=1~n
{
ll res=1;
for(int i=1; i<=n; i++)res=res*(ll)i%mod;
res=qpow(res,mod-2);
p[n]=res;
for(int i=n-1;i>=0;i--)
p[i]=p[i+1]*(i+1)%mod;
}
ll polysum(int n,ll *a,ll m)//a[1]...a[n] a[m]
{
if(1<=m&&m<=(ll)n)
return a[(int)m];
ll res=0;
p1[1]=p2[n]=1;
for(int i=2; i<=n; i++)p1[i]=p1[i-1]*(ll)(m-i+1)%mod;
for(int i=n-1; i>=1; i--)p2[i]=p2[i+1]*(ll)(m-i-1)%mod;
for(int i=1; i<=n; i++)
{
ll tmp=p[i-1]*p[n-i]%mod;
if((n-i)&1)tmp=tmp*(mod-1)%mod;
res=(res+a[i]*p1[i]%mod*p2[i]%mod*tmp%mod)%mod;
}
return res;
}
}
ll n,a[N];
int k;
int main()
{
cin>>n>>k;
polysum::init(k+2);
a[0]=0;
for(int i=1; i<=k+2; i++)
a[i]=(a[i-1]+polysum::qpow(i,k))%mod;
cout<<polysum::polysum(k+2,a,n);
return 0;
}