大概就是已知若干个点值,然后可以用组合的性质用自己把自己带进去然后O(M)得到任意一个点值把。(M为多项式的次数),组合数还是很神奇的。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define N 500005
#define mod 1000000007
using namespace std;
int n,m,cnt,a[N],b[N],c[N],u[N],v[N],pw[N],fac[N],inv[N],p[N];
int ksm(int x,int y){
int t=1; for (; y; y>>=1,x=(ll)x*x%mod) if (y&1) t=(ll)t*x%mod;
return t;
}
void pfs(){
int i,j; pw[1]=1;
for (i=2; i<=m+1; i++){
if (!pw[i]){ pw[i]=ksm(i,m); c[++cnt]=i; }
for (j=1; j<=cnt && i*c[j]<=m+1; j++){
pw[i*c[j]]=(ll)pw[i]*pw[c[j]]%mod;
if (!(i%c[j])) break;
}
}
}
int cbn(int x,int y){
return (ll)fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int main(){
scanf("%d%d",&n,&m); int i;
if (m==1){ printf("%d\n",((ll)n*(n+1)>>1)%mod); return 0; }
pfs();
if (n<=m){
int ans=0,base=m;
for (i=1; i<=n; i++,base=(ll)base*m%mod) ans=((ll)base*pw[i]+ans)%mod;
printf("%d\n",ans); return 0;
}
inv[0]=inv[1]=fac[0]=fac[1]=1;
for (i=2; i<=m+1; i++){
inv[i]=mod-(ll)inv[mod%i]*(mod/i)%mod;
fac[i]=(ll)fac[i-1]*i%mod;
}
a[0]=1; b[0]=0;
for (i=1; i<=m+1; i++){
a[i]=(ll)a[i-1]*inv[m]%mod; b[i]=((ll)b[i-1]*inv[m]+pw[i])%mod;
}
for (i=1; i<=m+1; i++) inv[i]=(ll)inv[i-1]*inv[i]%mod;
int t1=0,t2=0;
for (i=0; i<=m+1; i++){
int tmp=cbn(m+1,i); if (i&1) tmp=mod-tmp;
t1=((ll)tmp*a[i]+t1)%mod; t2=((ll)tmp*b[i]+t2)%mod;
}
p[0]=(ll)(mod-t2)*ksm(t1,mod-2)%mod;
for (i=1; i<=m; i++) p[i]=((ll)p[0]*a[i]+b[i])%mod;
u[0]=1; v[m]=1; int ans=0;
for (i=1; i<=m; i++) u[i]=(ll)u[i-1]*(n-i+1)%mod;
for (i=m-1; i>=0; i--) v[i]=(ll)v[i+1]*(n-i-1)%mod;
for (i=0; i<=m; i++){
int tmp=(ll)u[i]*v[i]%mod*inv[i]%mod*inv[m-i]%mod;
if ((m^i)&1) tmp=mod-tmp;
ans=((ll)p[i]*tmp+ans)%mod;
}
printf("%d\n",((ll)ans*ksm(m,n)-p[0]+mod)%mod);
return 0;
}
by lych
2016.3.17