如果你WA70pts

P4245 【模板】任意模数多项式乘法

xuyiyang @ 2023-11-25 13:34:36

开 long double,注意 FFT 单位根预处理不能用乘法,如:

w[0].a = 1;
cp t(cos(2 * pi / k), sin(2 * pi / k));
for (int i = 1; i < k; i ++ ) w[i] = w[i - 1] * t;

要这样:

for (int i = 0; i < k; i ++ ) w[i] = cp(cos(i * 2 * pi / k), sin(i * 2 * pi / k));

还有一些取模问题。以下是我的 MTT ,供参考。

void MTT(int P)
{
    int bit = log_2(n + m); k = 1 << bit + 1;
    for (int i = 0; i < k; i ++ ) r[i] = r[i >> 1] >> 1 | (i & 1) << bit;
    for (int i = 0; i < k; i ++ ) w[i] = cp(cos(i * 2 * pi / k), sin(i * 2 * pi / k));
    for (int i = 0; i < k; i ++ ) a[i] = cp((LD)(p[i] / L), (LD)(p[i] % L)), b[i] = cp((LD)(p[i] / L), (LD)(-p[i] % L));
    for (int i = 0; i < k; i ++ ) c[i] = cp((LD)(q[i] / L), (LD)(q[i] % L));
    FFT(a, 1); FFT(b, 1); FFT(c, 1); // FFT 正常写即可。
    for (int i = 0; i < k; i ++ ) c[i].a /= k, c[i].b /= k;
    for (int i = 0; i < k; i ++ ) a[i] = a[i] * c[i];
    for (int i = 0; i < k; i ++ ) b[i] = b[i] * c[i];
    FFT(a, 0); FFT(b, 0);
    for (int i = 0; i <= n + m; i ++ )
    {
    LL a1b1 = (LL)floor((a[i].a + b[i].a) / 2 + 0.5) % P;
    LL a1b2 = (LL)floor((a[i].b + b[i].b) / 2 + 0.5) % P;
    LL a2b1 = (LL)(floor(a[i].b + 0.5) - a1b2) % P;
    LL a2b2 = (LL)(floor(b[i].a + 0.5) - a1b1) % P;
    res[i] = ((a1b1 * L % P * L % P + (a1b2 + a2b1) % P * L % P) % P + a2b2) % P;
    res[i] = (res[i] % P + P) % P;
    }
}

|