题目大意:给你一个长度为(n)的数组,求(f_k=sum_{i=1}^na_i^k(1leqslant kleqslant n))
猜测是两个多项式相乘/除,又乱猜出那两个多项式,就可以通过此题
设(S={1,2,3,dots,n}),(t_i=sum_{Tsubseteq S,|T|=i}prod_{win T}a_w),(t_0=1)。
设(p_{i,j}=sum_{k=1}^na_k^jsum_{Tsubseteq(S-lbrace k brace),|T|=i-j}prod_{win T}a_w),特别地,当(j=i),(p_{i,j}=f_i),当(j>i),(p_{i,j}=0)。易证,(p_{i,1}=it_i)。
容易发现(f_it_j=p_{i+j,i}+p_{i+j,i+1})(可从最高次项的指数推导,(f_i imes t_j)最高次项的指数为(i)或(i+1))。
于是(sum_{j=0}^{i-1}(-1)^{i-j}f_{i-j}t_{j}=-p_{i,1}=-i*t_i),(t_i)可分治求出((t_i)为(prod_{j=1}^n(a_jx+1))的(i)次项),令(G(x)=sum_{i=0}^n-it_i),(H(x)=sum_{i=0}^nt_i),则(f_k)即(frac{G(x)}{H(x)})的(i)次项乘((-1)^i)。
抄板子多项式求逆
code:
#include<stdio.h>
#include<algorithm>
#include<stack>
#include<cctype>
#define inf 998244353
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline int R(){
char t=GC;
int x=0;
while(!isdigit(t)) t=GC;
while(isdigit(t)) x=x*10+t-48,t=GC;
return x;
}
int _0[1048576],_lset=-1;
inline void mod(int &p){while(p>=inf)p-=inf;}
inline int ksm(long long a,int b){register int ans=1;while(b)(b&1)&&(ans=a*ans%inf),a=a*a%inf,b>>=1;return ans;}
inline void init(int n){if(_lset==n)return;_lset=n;_0[0]=0;for(register int i=1;i<n;i++)_0[i]=i&1?_0[i^1]|n>>1:_0[i>>1]>>1;}
inline void mul(int a[],int b[],int n){for(register int i=0;i<n;i++)a[i]=1ll*a[i]*b[i]%inf;}
inline void clr(int a[],int l,int r){for(register int i=l;i<r;i++)a[i]=0;}
inline void cpy(int a[],int b[],int n){for(register int i=0;i<n;i++)b[i]=a[i];}
inline void ntt(int a[],int n,bool typ){
init(n);
for(register int i=0;i<n;i++)if(i<_0[i])a[i]^=a[_0[i]]^=a[i]^=a[_0[i]];
for(register int i=1;i<n;i<<=1){register int w=ksm(typ?332748118:3,(inf-1>>1)/i);
for(register int j=0;j<n;j+=i<<1){register long long h=1;
for(register int k=0;k<i;k++,h=w*h%inf){
register int p=a[j+k],q=h*a[i+j+k]%inf;
mod(a[j+k]=p+q);mod(a[i+j+k]=p+inf-q);
}
}
}if(typ){
register long long t=ksm(n,inf-2);
for(int i=0;i<n;i++)a[i]=t*a[i]%inf;
}
}
inline void getinv(int a[],int b[],int tmp[],int n){
clr(b,0,n<<1);
b[0]=ksm(a[0],inf-2);
for(int i=1;i<n;i<<=1){
clr(tmp,0,i<<2);
cpy(a,tmp,i<<1);
ntt(tmp,i<<2,0);
ntt(b,i<<2,0);
mul(tmp,b,i<<2);
mul(tmp,b,i<<2);
for(int j=0;j<i<<2;j++)mod(tmp[j]=b[j]+inf-tmp[j]),mod(tmp[j]+=b[j]);
cpy(tmp,b,i<<2);
ntt(b,i<<2,1);
clr(b,i<<1,i<<2);
}
}
int a[1048576],b[1048576],c[1048576],t[1048576],n,m,pool[102][524288],dat[200002],T;
std::stack<int>hdhd;
inline int gett(int n){while(n!=(n&-n))n^=n&-n;return n<<=1;}
int gett(int l,int r){
if(l==r){
int h=hdhd.top();hdhd.pop();
pool[h][0]=1;
pool[h][1]=dat[l];
pool[h][2]=0;
pool[h][3]=0;
return h;
}int p=gett(l,l+r>>1),q=gett(l+r+2>>1,r),topp=gett((l+r>>1)-l+1),topq=gett(r-(l+r>>1)),top=gett(r-l+1);
if(topp!=top)clr(pool[p],topp,top);
if(topq!=top)clr(pool[q],topq,top);
ntt(pool[p],top,0);
ntt(pool[q],top,0);
mul(pool[p],pool[q],top);
ntt(pool[p],top,1);
hdhd.push(q);
return p;
}
int main(){
T=R();
while(T--){
m=R();n=gett(m+1);
for(int i=1;i<=m;i++)dat[i]=R();
clr(t,0,n<<1);
while(!hdhd.empty())hdhd.pop();
for(int i=0;i<=100;i++)hdhd.push(i);
int p=gett(1,m);t[0]=1;
for(int i=1;i<=m;i++)t[i]=pool[p][i];
getinv(t,b,c,n);
clr(a,0,n<<1);
for(int i=1;i<=m;i++)a[i]=1ll*(inf-i)*t[i]%inf;
ntt(a,n<<1,0);
ntt(b,n<<1,0);
mul(a,b,n<<1);
ntt(a,n<<1,1);int ans=0;
for(int i=1;i<=m;i++)ans^=(i&1?(a[i]?inf-a[i]:0):a[i]);
printf("%d
",ans);
}
}