2019.01.01 bzoj3625:小朋友和二叉樹(生成函式+多項式求逆+多項式開方)
阿新 • • 發佈:2019-01-02
傳送門
生成函式好題。
卡場差評至今未過
題意簡述:
個點的二叉樹,每個點的權值KaTeX parse error: Expected 'EOF', got '\inC' at position 4: v_i\̲i̲n̲C̲=\{a_1,a_2,...a…,定義一棵樹的權值為所有點的權值之和,問有多少棵樹滿足其權值等於
對每個點的值構造生成函式
,令
表示答案的生成函式。
那麼
注意空樹的情況,這個遞推式相當於考慮自己的權值以及左右子樹的權值
然後解方程:
然後上多項式開方和多項式求逆即可。
悲傷的故事:封裝了一波多項式運算導致常數太大,於是只能在
上水過,
至今未過
程式碼:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
typedef long long ll;
const int mod=998244353;
int n,lim,tim,m;
vector<int>A,B,pos,Inv;
#define add(a,b) ((a)+(b)>=mod?(a)+(b)-mod:(a)+(b))
#define dec(a,b) ((a)>=(b)?(a)-(b):(a)-(b)+mod)
#define mul(a,b) ((ll)(a)*(b)%mod)
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)ret=mul(ret,a);return ret;}
inline void ntt(vector<int>&a,const int&type){
for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
for(ri mid=1,wn,mult=(mod-1)/2,typ=type==1?3:(mod+1)/3;mid<lim;mid<<=1,mult>>=1){
wn=ksm(typ,mult);
for(ri j=0,len=mid<<1;j<lim;j+=len)for(ri w=1,a0,a1,k=0;k<mid;++k,w=mul(w,wn)){
a0=a[j+k],a1=mul(w,a[j+k+mid]);
a[j+k]=add(a0,a1),a[j+k+mid]=dec(a0,a1);
}
}
if(type==-1)for(ri i=0,inv=ksm(lim,mod-2);i<lim;++i)a[i]=mul(a[i],inv);
}
inline void init(const int&up){
lim=1,tim=0;
while(lim<=up)lim<<=1,++tim;
pos.resize(lim),pos[0]=0;
for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
}
struct poly{
vector<int>a;
inline int deg()const{return a.size()-1;}
poly(int k,int x=0){a.resize(k+1),a[k]=x;}
inline int&operator[](const int&k){return a[k];}
inline const int&operator[](const int&k)const{return a[k];}
inline poly extend(const int&k){poly ret=*this;return ret.a.resize(k),ret;}
friend inline poly operator+(const poly&a,const poly&b){
poly ret(max(a.deg(),b.deg()));
for(ri i=0;i<=a.deg();++i)ret[i]=add(ret[i],a[i]);
for(ri i=0;i<=b.deg();++i)ret[i]=add(ret[i],b[i]);
return ret;
}
friend inline poly operator-(const poly&a,const poly&b){
poly ret(max(a.deg(),b.deg()));
for(ri i=0;i<=a.deg();++i)ret[i]=add(ret[i],a[i]);
for(ri i=0;i<=b.deg();++i)ret[i]=dec(ret[i],b[i]);
return ret;
}
friend inline poly operator*(const int&a,const poly&b){
poly ret(b.deg());
for(ri i=0;i<=b.deg();++i)ret[i]=mul(a,b[i]);
return ret;
}
friend inline poly operator*(const poly&a,const poly&b){
int n=a.deg(),m=b.deg();
init(n+m),A.resize(lim),B.resize(lim);
poly ret(lim-1);
for(ri i=0;i<=n;++i)A[i]=a[i];
for(ri i=0;i<=m;++i)B[i]=b[i];
for(ri i=n+1;i<lim;++i)A[i]=0;
for(ri i=m+1;i<lim;++i)B[i]=0;
ntt(A,1),ntt(B,1);
for(ri i=0;i<lim;++i)A[i]=mul(A[i],B[i]);
return ntt(A,-1),ret.a=A,ret;
}
inline poly poly_inv(poly a,const int&k){
a=a.extend(k);
if(k==1)return poly(0,ksm(a[0],mod-2));
poly f0=poly_inv(a,(k+1)>>1);
return (2*f0-((f0*f0.extend(k))*a).extend(k)).extend(k);
}
inline poly poly_sqrt(poly a,const int&k){
a=a.extend(k);
if(k==1)return poly(0,1);
poly f0=poly_sqrt(a,(k+1)>>1).extend(k);
return (((f0*f0).extend(k)+a)*poly_inv((2*f0),k)).extend(k);
}
};
int main(){
n=read(),m=read();
int len;
for(len=1;len<=m;len<<=1);
poly sqr=(len);
for(ri i=1,v;i<=n;++i){
v=read();
if(v<=m)sqr[v]=mod-4;
}
++sqr[0],sqr=sqr.poly_sqrt(sqr,len),++sqr[0],sqr=sqr.poly_inv(sqr,len);
for(ri i=1;i<=m;++i)cout<<mul(sqr[i],2)<<'\n';
return 0;
}