題目大意:給定
1.父親節點的標號大於子節點
2.一個點如果有兒子,則有兩個無序的
3.如果一個點是根節點或
由於有標號,所以這裏顯然要使用指數級生成函數
設
那麼考慮:
根節點是固定的,不參與標號的排列,首先把根節點刨掉,即:
然後一棵樹可能只有一個葉節點,刨掉之後就什麼都不剩了;
也可能有兒子,這時候兒子分爲三部分:
故直觀上來看應該是
可以列出方程:
這個方程怎麼解?
牛頓迭代。
假設現在我們有待定多項式
老辦法,倍增處理。
假設我們已經知道了
泰勒展開:
看到這裏學過微積分的人已經會構造了吧。
令
等式兩邊同乘
裏面的一切計算都是
注意常數……
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 530000
#define MOD 998244353
#define G 3
using namespace std;
int n,m,d;
long long inv[M];
int A[M],B[M];
void Linear_Shaker()
{
int i;
for(inv[1]=1,i=2;i<=d<<1;i++)
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
}
long long Quick_Power(long long x,int y)
{
long long re=1;
while(y)
{
if(y&1) (re*=x)%=MOD;
(x*=x)%=MOD; y>>=1;
}
return re;
}
void FFT(int a[],int n,int type){
static int rev_bit[M];
int i,j,k,w,wn,t,bit;
for(bit=0;1<<bit<n;++bit);
static int b[M];
for(i=0;i<n;i++)
rev_bit[i]=(rev_bit[i>>1]>>1)|((i&1)<<bit-1);
for(i=0;i<n;i++)
if(i<rev_bit[i])
swap(a[i],a[rev_bit[i]]);
for(k=2;k<=n;k<<=1)
for(wn=Quick_Power(G,(long long)(MOD-1)/k*type%(MOD-1)),i=0;i<n;i+=k)
for(w=1,j=0;j<k>>1;++j,w=(long long)w*wn%MOD)
{
t=(long long)w*a[i+j+(k>>1)]%MOD;
a[i+j+(k>>1)]=a[i+j]-t<0?a[i+j]-t+MOD:a[i+j]-t;
a[i+j]=a[i+j]+t>=MOD?a[i+j]+t-MOD:a[i+j]+t;
}
if(type!=1)
{
for(i=0;i<n;i++)
a[i]=(long long)a[i]*inv[n]%MOD;
}
}
void Get_Inv(int a[],int b[],int n)
//求a的逆,長度爲n,結果儲存在b中。
//要求傳入時b[0...n<<1]爲空。
{
static int temp[M];
int i;
if(n==1)
{
b[0]=Quick_Power(a[0],MOD-2);
return ;
}
Get_Inv(a,b,n>>1);
memcpy(temp,a,sizeof(a[0])*n);
memset(temp+n,0,sizeof(a[0])*n);
FFT(temp,n<<1,1);
FFT(b,n<<1,1);
for(i=0;i<n<<1;i++)
temp[i]=(long long)b[i]*(2-(long long)temp[i]*b[i]%MOD+MOD)%MOD;
FFT(temp,n<<1,MOD-2);
memcpy(b,temp,sizeof(a[0])*n);
memset(b+n,0,sizeof(a[0])*n);
}
void Get_Ln(int a[],int b[],int n)
//求a的ln,長度爲n,結果儲存在b中。
//要求a的常數項爲1。
{
static int a_[M],a_inv[M];
int i;
Get_Inv(a,a_inv,n);
for(i=0;i<n-1;i++)
a_[i]=(long long)a[i+1]*(i+1)%MOD;
FFT(a_,n<<1,1);
FFT(a_inv,n<<1,1);
for(i=0;i<n<<1;i++)
b[i]=(long long)a_[i]*a_inv[i]%MOD;
FFT(b,n<<1,MOD-2);
for(i=n-1;i;i--)
b[i]=b[i-1]*inv[i]%MOD;
b[0]=0;
memset(b+n,0,sizeof(b[0])*n);
memset(a_,0,sizeof(a_[0])*n<<1);
memset(a_inv,0,sizeof(a_inv[0])*n<<1);
}
void Get_Exp(int a[],int b[],int n)
//求a的exp,長度爲n,結果儲存在b中。
//要求傳入時b[0...n<<1]爲空。
//要求a的常數項爲0。
{
static int temp[M];
int i;
if(n==1)
{
b[0]=1;
return ;
}
Get_Exp(a,b,n>>1);
Get_Ln(b,temp,n);
for(i=0;i<n;i++)
temp[i]=((i==0)+MOD-temp[i]+a[i])%MOD;
FFT(temp,n<<1,1);
FFT(b,n<<1,1);
for(i=0;i<n<<1;i++)
b[i]=(long long)b[i]*temp[i]%MOD;
FFT(b,n<<1,MOD-2);
memset(b+n,0,sizeof(b[0])*n);
}
void Newton_Method(int a[],int b[],int n)
//求解常微分方程dx/dt=ax^2/2+1,長度爲n,結果儲存在b中。
//要求傳入時b[0...n<<1]爲空。
//x[2n]=int( (1-ax^2/2)*r )/r
//r=exp(-int(ax))
{
static int temp[M],temp_temp[M],r[M],r_temp[M];
int i;
if(n==1)
{
b[0]=0;
return ;
}
Newton_Method(a,b,n>>1);
memcpy(temp,a,sizeof(a[0])*n);
memset(temp+n,0,sizeof(a[0])*n);
FFT(temp,n<<1,1);
FFT(b,n<<1,1);
for(i=0;i<n<<1;i++)
temp_temp[i]=(long long)temp[i]*b[i]%MOD;
FFT(temp_temp,n<<1,MOD-2);
for(i=n-1;i;i--)
temp_temp[i]=temp_temp[i-1]*inv[i]%MOD*(MOD-1)%MOD;
temp_temp[0]=0;
memset(r,0,sizeof(a[0])*n<<1);
Get_Exp(temp_temp,r,n);
for(int i=0;i<n<<1;i++)
temp[i]=(1+inv[2]*(MOD-1)%MOD*temp[i]%MOD*b[i]%MOD*b[i]%MOD)%MOD;
FFT(temp,n<<1,MOD-2);
memset(temp+n,0,sizeof(a[0])*n);
memcpy(r_temp,r,sizeof(a[0])*n<<1);
FFT(temp,n<<1,1);
FFT(r_temp,n<<1,1);
for(int i=0;i<n<<1;i++)
temp[i]=(long long)temp[i]*r_temp[i]%MOD;
FFT(temp,n<<1,MOD-2);
for(i=n-1;i;i--)
temp[i]=temp[i-1]*inv[i]%MOD;
temp[0]=0;
memset(temp+n,0,sizeof(a[0])*n);
memset(r_temp,0,sizeof(a[0])*n<<1);
Get_Inv(r,r_temp,n);
FFT(temp,n<<1,1);
FFT(r_temp,n<<1,1);
for(int i=0;i<n<<1;i++)
b[i]=(long long)temp[i]*r_temp[i]%MOD;
FFT(b,n<<1,MOD-2);
memset(b+n,0,sizeof(a[0])*n);
memset(temp+n,0,sizeof(a[0])*n);
}
int main()
{
cin>>n;
for(d=1;d<=n+1;d<<=1);
Linear_Shaker();
long long temp=1;
for(int i=0;i<n;i++)
{
scanf("%1d",&A[i]);
A[i]=A[i]*temp;
(temp*=inv[i+1])%=MOD;
}
Newton_Method(A,B,d);
temp=1;
for(int i=1;i<=n;i++)
{
(temp*=i)%=MOD;
printf("%d\n",int(B[i]*temp%MOD));
}
return 0;
}