【题解】「THUPC 2017」小 L 的计算题 / Sum

题目链接

题目大意:给你一个长度为\(n\)的数组,求\(f_k=\sum_{i=1}^na_i^k(1\leqslant k\leqslant n)\)

解法:

\(S={1,2,3,\dots,n}\)\(t_i=\sum_{T\subseteq S,|T|=i}\prod_{w\in T}a_w\)\(t_0=1\)

\(p_{i,j}=\sum_{k=1}^na_k^j\sum_{T\subseteq(S-\lbrace k\rbrace),|T|=i-j}\prod_{w\in 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\times 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\n",ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/ztc03/p/THUPC2017Sum.html