bzoj3625
fft
分治虽然是万能的,但是太慢了
分治是nlog^2n的,太慢了,于是我们用求逆和开根
设f(x)表示答案为x的方案数
c表示物品的生成函数
那么f=f*f*c+1
f*f表示左右儿子的方案数
c表示根的方案数
+1是空树,也就是+上t(x)=1这个生成函数
然后求根公式得出f=2/(1+sqrt(1-4*g))
为什么是+号呢?因为x=1时方案数=1,那么只能是+号
然后就是多项式开根和求逆
具体看picks博客
然后是卡常
所有数组开int
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; }