#include #include #include #include #include #include using namespace std; typedef long long LL; typedef unsigned int uint; LL ww[101]; LL* e = ww + 50; const int MAXN = 1e5 + 5; const LL P = 998244353; LL qpow(LL a, LL k, LL p) { LL c = 1; a %= p; while (k) { if (k & 1) c = (c * a) % p; k >>= 1; a = (a * a) % p; } return c; } void primeroot(LL* e, const LL& P, const LL& g) { int s = 0; LL q = P - 1; //`将$p$分解成$p=q\times2^s+1$的形式` while ((q & 1) == 0) {s++; q >>= 1;} //`计算$q$和$s$` LL w = qpow(g, q, P); //`先计算$2^s$次原根$g^{\frac{p-1}{2^s}}$` LL invw = qpow(w, P - 2, P); //`$2^s$次原根的逆元` for (int h = s; h >= 0; h--) { e[h] = w; //`$e[h]=g^{\frac{p-1}{2^h}}$` e[-h] = invw; //`$e[-h]=g^{-\frac{p-1}{2^h}}$` w = (w * w) % P; //`$2^{h}$次原根的平方等于$2^{h-1}$次原根` invw = (invw * invw) % P; } } void ntt(LL* f, const int& h, const int& type) { if (h == 0) return; //`递归出口` LL f0[1 << (h - 1)], f1[1 << (h - 1)]; //`新建两个大小为$2^{h-1}$的数组` int n = 1 << h; //`$n=2^h$` for (int i = 0; i < n; i += 2) f0[i / 2] = f[i]; //`偶数项复制到f0` ntt(f0, h - 1, type); //`将f0转成点值,$f0[k]=f_0(g_{n/2}^{k})$` for (int i = 1; i < n; i += 2) f1[i / 2] = f[i]; //`奇数项复制到f1` ntt(f1, h - 1, type); //`将f1转成点值,$f1[k]=f_1(g_{n/2}^{k})$` LL w = e[type * h]; //`得到$n$次原根$g_n=e[h]=g^{\frac{p-1}{2^h}}$` LL x = 1; //`用变量x计算$g_n^k$` for (int k = 0; k < n / 2; k++) { //`$k$的枚举范围是$n/2$` f[k] = f0[k] + x * f1[k]; //`$f(g_n^k) \equiv f_0(g_{n/2}^{k})+g_n^kf_1(g_{n/2}^{k})$` f[k] %= P; //`$\pmod p$` f[k + n / 2] = f0[k] - x * f1[k]; //`$f(g_n^{k+n/2}) \equiv f_0(g_{n/2}^{k})-g_n^kf_1(g_{n/2}^{k})$` f[k + n / 2] %= P; //`$\pmod p$` x *= w; x %= P; //`保持$x \equiv g_n^k \pmod p$` } } void polyInv(int n, LL* f, LL* g) { if (n == 1) { //`只有一项时` g[0] = qpow(f[0], P - 2, P); //`令g[0]等于f[0]模$p$的乘法逆元` return; } polyInv((n + 1) >> 1, f, g); //`递归调用polyInv,计算$\bmod {x^{\left\lceil \frac{n}{2} \right\rceil}}$的逆` int deg = 1, h = 0; while (deg < 2 * n) {deg <<= 1; h++;} //`取$2^h$为大于等于$2n$的最小的$2$的幂` LL a[deg]; for(int i=0;i f[MAXN/2]; vector g[MAXN/2]; LL F1[MAXN*4],F2[MAXN*4],G1[MAXN*4],G2[MAXN*4]; void addFrac(int i1,int i2){ int limit=f[i1].size()+f[i2].size()-1;//分母f1*f2的项数 int deg=1,h=0; while(deg1){ for(int i=0;i