标签:its https and bit c++ ret binary logs public
大致题意: 给你\(n\)个数,对于\(i∈[1,m]\),求出有多少棵不同的二叉树,满足权值都取自这\(n\)个数中,且权值和恰为\(i\)。
我们令\(f_i\)表示权值和恰为\(i\)的二叉树个数,\(g_i\)表示\(i\)是否为给出的数(\(0/1\))。
对于\(f_0\),易知\(f_0=1\)。
对于\(f_n(n>0)\),一个显然的转移,我们枚举\(i\)表示根节点填的数,然后枚举\(j\)表示左子树权值和,就有:
然后发现这其实是一个卷积的形式。
令\(F,G\)分别为\(f,g\)的生成函数,得到:(注意最后的加\(1\)是因为\(f_0=1\))
接下来,最神奇的一步来了。根据一元二次方程的求根公式,得到:
考虑当\(F=\frac{1+\sqrt{1-4G}}{2G}\)时,\(F\)是不收敛的,故舍去。
而当\(F=\frac{1-\sqrt{1-4G}}{2G}\)时,\(F\)就能够满足要求了。
此时还可以进一步转化让式子更简单:分母无理化分子有理化。得到:
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define V 100000
#define X 998244353
using namespace std;
int n,m,g[V<<2],s[V<<2];
I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
class Poly//多项式
{
private:
int P,L,R[V<<2],t[V<<2],k[V<<2],PR,IPR,I2;
I void T(int *s,CI p)//NTT
{
RI i,j,k,U,S,x,y;for(i=0;i^P;++i) i<R[i]&&(x=s[i],s[i]=s[R[i]],s[R[i]]=x);
for(i=1;i^P;i<<=1) for(U=QP(p,(X-1)/(i<<1)),j=0;j^P;j+=i<<1) for(S=1,k=0;k^i;
S=1LL*S*U%X,++k) s[j+k]=((x=s[j+k])+(y=1LL*S*s[i+j+k]%X))%X,s[i+j+k]=(x-y+X)%X;
}
public:
I Poly() {PR=3,IPR=QP(3,X-2),I2=X+1>>1;}
I void Inv(CI n,int *a,int *b)//多项式求逆
{
if(!n) return (void)(b[0]=QP(a[0],X-2));Inv(n>>1,a,b);
RI i;P=1,L=0;W(P<=(n<<1)) P<<=1,++L;for(i=0;i^P;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
for(i=0;i<=n;++i) t[i]=a[i];W(i^P) t[i++]=0;
for(T(b,PR),T(t,PR),i=0;i^P;++i) b[i]=(2LL*b[i]-1LL*t[i]*b[i]%X*b[i]%X+X)%X;
RI t=QP(P,X-2);for(T(b,IPR),i=0;i<=n;++i) b[i]=1LL*b[i]*t%X;W(i^P) b[i++]=0;
}
I void Sqrt(CI n,int *a,int *b)//多项式开根
{
if(!n) return (void)(b[0]=1);Sqrt(n>>1,a,b);
RI i;P=1,L=0;W(P<=(n<<1)) P<<=1,++L;for(i=0;i^P;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
for(i=0;i^P;++i) k[i]=0;for(Inv(n,b,k),i=0;i<=n;++i) t[i]=a[i];W(i^P) t[i++]=0;
for(T(t,PR),T(b,PR),T(k,PR),i=0;i^P;++i) b[i]=(1LL*b[i]*b[i]+t[i])%X*k[i]%X*I2%X;
RI t=QP(P,X-2);for(T(b,IPR),i=0;i<=n;++i) b[i]=1LL*b[i]*t%X;W(i^P) b[i++]=0;
}
}P;
int main()
{
RI i,x;for(scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",&x),g[x]=1;
for(g[0]=i=1;i<=V;++i) g[i]=X-4LL*g[i]%X;P.Sqrt(V,g,s),++s[0]==X&&(s[0]=0);//把g修改为1-4g,令s=1+sqrt(1-4g)
for(memset(g,0,sizeof(g)),P.Inv(V,s,g),i=1;i<=m;++i) printf("%d\n",2LL*g[i]%X);//把g修改为1/(1+sqrt(1-4g)),系数乘2即为答案
return 0;
}
【CF438E】The Child and Binary Tree(生成函数+多项式开根)
标签:its https and bit c++ ret binary logs public
原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF438E.html