# bzoj3625

fft

c表示物品的生成函数

f*f表示左右儿子的方案数

c表示根的方案数

+1是空树，也就是+上t(x)=1这个生成函数

fft蝴蝶操作一定要开int

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int P = 998244353;
ll power(ll x, int t)
{
ll ret = 1;
for(; t; t >>= 1, x = x * x % P) if(t & 1) ret = ret * x % P;
return ret;
}
const int N = (1 << 18) + 2;
int n, k, m;
int rev[N];
ll inv2;
void ntt(int *a, int n, int k, int f)
{
for(int i = 0; i < n; ++i) if(i < rev[i]) swap(a[i], a[rev[i]]);
for(int l = 2; l <= n; l <<= 1)
{
ll w = power(3, f == 1 ? (P - 1) / l : P - 1 - (P - 1) / l);
int m = l >> 1;
for(int i = 0; i < n; i += l)
{
ll t = 1;
for(int k = 0; k < m; ++k, t = t * w % P)
{
int x = a[i + k], y = t * a[i + k + m] % P;
a[i + k] = (x + y) % P;
a[i + m + k] = (x - y + P) % P;
}
}
}
if(f == -1)
{
ll inv = power(n, P - 2);
for(int i = 0; i < n; ++i) a[i] = a[i] * inv % P;
}
}
int a[N], b[N], tmp[N], B[N], c[N];
void poly_inverse(int *a, int *b, int l)
{
if(l == 1)
{
b[0] = power(a[0], P - 2);
return;
}
poly_inverse(a, b, l >> 1);
int n = 1, k = 0;
while(n <= l) n <<= 1, ++k;
for(int i = 0; i < n; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
for(int i = 0; i < l; ++i) tmp[i] = a[i];
for(int i = l; i < n; ++i) tmp[i] = 0;
ntt(tmp, n, k, 1);
ntt(b, n, k, 1);
for(int i = 0; i < n; ++i) b[i] = (ll)b[i] * (2 - (ll)tmp[i] * b[i] % P + P) % P;
ntt(b, n, k, -1);
for(int i = l; i < n; ++i) b[i] = 0;
}
void poly_sqrt(int *a, int *b, int l)
{
if(l == 1)
{
b[0] = 1;
return;
}
int n = 1, k = 0;
while(n <= l) n <<= 1, ++k;
poly_sqrt(a, b, l >> 1);
for(int i = 0; i < n; ++i) B[i] = 0;
poly_inverse(b, B, l);
for(int i = 0; i < n; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
for(int i = 0; i < l; ++i) tmp[i] = a[i];
for(int i = l; i < n; ++i) tmp[i] = 0, B[i] = 0;
ntt(B, n, k, 1);
ntt(tmp, n, k, 1);
ntt(b, n, k, 1);
for(int i = 0; i < n; ++i) b[i] = (ll)inv2 * (b[i] + (ll)B[i] * tmp[i] % P) % P;
ntt(b, n, k, -1);
for(int i = l; i < n; ++i) b[i] = 0;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
{
int x;
scanf("%d", &x);
c[x] -= 4;
}
inv2 = power(2, P - 2);
int len = 1;
while(len <= m) len <<= 1;
++c[0];
for(int i = 1; i <= m; ++i) if(c[i] < 0) c[i] += P;
poly_sqrt(c, b, len);
++b[0];
b[0] %= P;
poly_inverse(b, a, len);
for(int i = 1; i <= m; ++i) printf("%d\n", a[i] * 2 % P);
return 0;
}
View Code

posted @ 2017-12-19 09:08  19992147  阅读(...)  评论(...编辑  收藏