题意:
给定数组 A 1 . . . , A n A_1...,A_n A1...,An,对于所有 1 ≤ i ≤ k 1 \le i \le k 1≤i≤k,求 S i = ∑ j A j i S_i = \sum_{j}A_j^i Si=∑jAji。
题解:
这道题要用到一个叫牛顿恒等式的玩意儿。
对于 n n n次多项式 f = ∑ i = 0 n a i x i f=\sum_{i=0}^na_ix^i f=∑i=0naixi(注意是首一多项式),设其几个根分别为 x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1,x2,...,xn,设 b i = a n − i b_i =a_{n-i} bi=an−i,那么对于任意 k k k,有:
∑ j = 1 n S i b n − i + k b n = 0 \sum_{j=1}^n S_i b_{n-i}+kb_n = 0 j=1∑nSibn−i+kbn=0
这个东西在 k ≥ n k \ge n k≥n的时候只需要把 x i x_i xi分别带入 f f f然后相加即可得到,小于的时候可以用归纳法证明(当然我不会)。
然后分治FFT+多项式求逆即可。 时间复杂度 O ( n log 2 n + k log k ) O(n \log^2 n + k \log k) O(nlog2n+klogk)。
#include
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void W(int x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+'0');
}
const int N=2e6+50, mod=998244353;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (long long)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
namespace FFT {
int k,w[N],pos[N],A[N],B[N];
inline void init(int n) {
for(k=1;k<=n;k<<=1);
for(int i=1;i<k;i++)
pos[i]=(i&1) ? ((pos[i>>1]>>1)^(k>>1)) : (pos[i>>1]>>1);
memset(A,0,sizeof(int)*k);
memset(B,0,sizeof(int)*k);
}
inline void dft(int *a) {
for(int i=1;i<k;i++)
if(pos[i]>i) swap(a[pos[i]],a[i]);
for(int bl=1;bl<k;bl<<=1) {
int tl=bl<<1, wn=power(3,(mod-1)/tl);
w[0]=1; for(int i=1;i<bl;i++) w[i]=mul(w[i-1],wn);
for(int bg=0;bg<k;bg+=tl)
for(int j=0;j<bl;j++) {
int &t1=a[bg+j],&t2=a[bg+j+bl],t=mul(t2,w[j]);
t2=dec(t1,t); t1=add(t1,t);
}
}
}
inline void opt() {
dft(A); dft(B);
for(int i=0;i<k;i++) A[i]=mul(A[i],B[i]);
dft(A); reverse(A+1,A+k);
const int inv=power(k,mod-2);
for(int i=0;i<k;i++) A[i]=mul(A[i],inv);
}
}
struct poly {
vector <int> a;
poly(int x=0,int y=0) {a.resize(x+1); a[x]=y;}
inline int deg() const {return a.size()-1;}
inline int& operator [](int x) {return a[x];}
inline const int& operator [](int x) const{return a[x];}
inline poly extend(int len) {poly c=*this; c.a.resize(len+1); return c;}
inline poly rev() {poly c=*this; reverse(c.a.begin(),c.a.end()); return c;}
friend inline poly operator *(const poly &a,const poly &b) {
poly c(a.deg()+b.deg());
FFT::init(c.deg());
for(int i=0;i<=a.deg();i++) FFT::A[i]=a[i];
for(int i=0;i<=b.deg();i++) FFT::B[i]=b[i];
FFT::opt();
for(int i=0;i<=c.deg();i++) c[i]=FFT::A[i];
return c;
}
inline poly mul(int b) {
poly c=*this;
for(int i=0;i<=c.deg();i++) c[i]=::mul(c[i],b);
return c;
}
friend inline poly operator -(const poly &a,const poly &b) {
poly c(max(a.deg(),b.deg()));
for(int i=0;i<=a.deg();i++) c[i]=add(c[i],a[i]);
for(int i=0;i<=b.deg();i++) c[i]=dec(c[i],b[i]);
return c;
}
inline poly calc_inv(poly f,int len) {
if(len==1) {return poly(0,power(f[0],mod-2));}
poly f0=calc_inv(f.extend(len/2-1),len/2);
return (f0.mul(2)-(f*f0).extend(len-1)*f0).extend(len-1);
}
inline poly calc_inverse(int len) {
int k; for(k=1;k<=len;k<<=1);
poly f=*this; f.extend(k);
return calc_inv(f,k).extend(len);
}
};
int n,k;
inline poly solve(int l,int r) {
if(l==r) {
poly c(1,1);
c[0]=dec(0,rd());
return c;
}
int mid=(l+r)>>1;
return solve(l,mid)*solve(mid+1,r);
}
int main() {
n=rd(), k=rd();
poly b=solve(1,n);
b=b.rev(); poly a=b;
for(int i=0;i<=n;i++) a[i]=mul(b[i],mod-i);
a=(a*b.calc_inverse(k)).extend(k);
for(int i=1;i<=k;i++) W(a[i]), putchar(' ');
}