题目传送门
分析:
这牛顿迭代真离谱
首先求烷基的话我们至少可以先找到根的位置
然后找一个生成函数(f)表达它
相当于每个点除了父亲还可以连出三个儿子
于是(f_n=sum_{i+j+k+1=n}f_{i}f_{j}f_{k})
空树时(f_0=1)
这个是没有考虑同构,同构时结合polya定理,置换大小为6
手玩一下:
(f(x)=xfrac{f^3(x)+3f(x)f(x^2)+2f(x^3)}{6})
怎么求啊。。。牛顿迭代走起来
求(f_0(x))时,我们能够知道(f_0(x^2),f_0(x^3))
套用式子(f(x)=f_0(x)-frac{G(f_0(x))}{G'(f_0(x))})
化简:
[f(x)=f_0(x)-frac{x(f_0^3(x)+3f_0(x)f_0(x^2)+2f_0(x^3))-6f_0(x)+6}{3f_0^2(x)+3f_0(x^2)-6}
]
NTT大礼包。。。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 2000005
#define MOD 998244353
using namespace std;
inline int getint()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
int F[maxn],rev[maxn];
inline int upd(int x){return x<MOD?x:x-MOD;}
inline int ksm(int num,int k)
{
int ret=1;
for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD;
return ret;
}
inline void getrev(int len)
{for(int i=0;i<len;i++)rev[i]=(rev[i>>1]>>1)|(i&1?len>>1:0);}
inline void NTT(int *A,int len,int opt)
{
for(int i=0;i<len;i++)if(i<rev[i])swap(A[i],A[rev[i]]);
for(int i=1;i<len;i<<=1)
{
int wn=ksm(3,(MOD-1)/(i<<1));
if(!~opt)wn=ksm(wn,MOD-2);
for(int j=0;j<len;j+=(i<<1))for(int k=0,w=1;k<i;k++,w=1ll*w*wn%MOD)
{
int x=A[j+k],y=1ll*A[i+j+k]*w%MOD;
A[j+k]=upd(x+y),A[i+j+k]=upd(x-y+MOD);
}
}
if(!~opt)for(int i=0,Inv=ksm(len,MOD-2);i<len;i++)A[i]=1ll*A[i]*Inv%MOD;
}
inline void getinv(int *A,int *B,int n)
{
static int T[maxn];
for(int i=0;i<(n<<1);i++)B[i]=0;
B[0]=ksm(A[0],MOD-2);
for(int len=2;len<=n;len<<=1)
{
for(int i=0;i<len;i++)T[i]=A[i],T[i+len]=0;
getrev(len<<1);
NTT(T,len<<1,1),NTT(B,len<<1,1);
for(int i=0;i<(len<<1);i++)B[i]=1ll*B[i]*upd(2-1ll*T[i]*B[i]%MOD+MOD)%MOD;
NTT(B,len<<1,-1);
for(int i=len;i<(len<<1);i++)B[i]=0;
}
}
inline void solve(int n)
{
static int G[maxn],H[maxn],S[maxn],C[maxn],T[maxn];
F[0]=1;
for(int i=2;i<=n;i<<=1)
{
for(int j=0;j<i;j++)T[j]=F[j],S[j]=C[j]=T[j+i]=S[j+i]=C[j+i]=0;
for(int j=0;j<i;j+=2)S[j]=F[j/2];
for(int j=0;j<i;j+=3)C[j]=F[j/3];
getrev(i<<1);
NTT(T,i<<1,1),NTT(S,i<<1,1);
for(int j=0;j<(i<<1);j++)G[j]=1ll*T[j]*(1ll*T[j]*T[j]%MOD+3ll*S[j])%MOD,H[j]=3*(1ll*T[j]*T[j]+S[j])%MOD;
NTT(G,i<<1,-1),NTT(H,i<<1,-1);
for(int j=i;j<(i<<1);j++)G[j]=H[j]=0;
for(int j=i-1;j;j--)G[j]=((1ll*G[j-1]+2ll*C[j-1]-6ll*F[j])%MOD+MOD)%MOD,H[j]=H[j-1];
G[0]=0,H[0]=MOD-6;
NTT(G,i<<1,1),getinv(H,T,i),NTT(T,i<<1,1);
for(int j=0;j<(i<<1);j++)G[j]=1ll*G[j]*T[j]%MOD;
NTT(G,i<<1,-1);
for(int j=0;j<i;j++)F[j]=(F[j]-G[j]+MOD)%MOD;
}
}
int main()
{
int len=1,n=getint();
while(len<=n)len<<=1;
solve(len);
printf("%d
",F[n]);
}