1 条题解
-
0
没学过 ntt 指路:https://blog.csdn.net/tenkuo/article/details/150500190

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef __int128 i128; const int N = 3e6 + 10; const LL MOD = 1000000007; const LL P1 = 998244353; const LL P2 = 1004535809; const LL P3 = 469762049; LL a1[N], b1[N], a2[N], b2[N], a3[N], b3[N]; LL ans1[N], ans2[N], ans3[N]; LL temp_a[N], temp_b[N]; int limit, l, r[N]; int n, m; LL q_pow(LL a, LL b, LL P) { LL c = 1; while (b) { if (b & 1) c = (i128)c * a % P; a = (i128)a * a % P; b >>= 1; } return c; } // NTT 实现 // type = 1: 正变换, type = -1: 逆变换 void ntt(LL *a, int type, LL P) { for (int i = 0; i < limit; i++) { if (i < r[i]) swap(a[i], a[r[i]]); } for (int mid = 1; mid < limit; mid <<= 1) { // 计算原根 g 的 (P-1)/(2*mid) 次方 LL Wn = q_pow(3, (P - 1) / (mid << 1), P); if (type == -1) { Wn = q_pow(Wn, P - 2, P); // 逆变换取逆 } for (int R = (mid << 1), j = 0; j < limit; j += R) { LL w = 1; for (int k = 0; k < mid; k++, w = (i128)w * Wn % P) { LL x = a[j + k]; LL y = (i128)a[j + mid + k] * w % P; a[j + k] = (x + y) % P; a[j + mid + k] = (x - y + P) % P; } } } // 如果是逆变换,乘以 inv_limit if (type == -1) { LL inv_limit = q_pow(limit, P - 2, P); for (int i = 0; i < limit; i++) { a[i] = (i128)a[i] * inv_limit % P; } } } void cvlt(LL *a, LL *b, LL *result, LL P) { // 复制数据并清零剩余部分 for (int i = 0; i < limit; i++) { temp_a[i] = (i < n) ? a[i] % P : 0; temp_b[i] = (i < m) ? b[i] % P : 0; } // 正变换 ntt(temp_a, 1, P); ntt(temp_b, 1, P); // 点乘 for (int i = 0; i < limit; i++) { temp_a[i] = (i128)temp_a[i] * temp_b[i] % P; } // 逆变换 ntt(temp_a, -1, P); // 复制结果 for (int i = 0; i < limit; i++) { result[i] = temp_a[i]; } } LL inv(LL a, LL mod) { return q_pow(a, mod - 2, mod); } LL crt(LL r1, LL r2, LL r3) { LL k1 = (r2 - r1) % P2; if (k1 < 0) k1 += P2; k1 = (i128)k1 * inv(P1 % P2, P2) % P2; i128 x12 = (i128)r1 + (i128)P1 * k1; i128 P12 = (i128)P1 * P2; LL r3_mod = (LL)(x12 % P3); LL k2 = (r3 - r3_mod) % P3; if (k2 < 0) k2 += P3; k2 = (i128)k2 * inv((LL)(P12 % P3), P3) % P3; i128 x = x12 + P12 * k2; x %= MOD; return (LL)x; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m; for (int i = 0; i < n; i++) { cin >> a1[i]; a2[i] = a3[i] = a1[i]; } for (int i = 0; i < m; i++) { cin >> b1[i]; b2[i] = b3[i] = b1[i]; } limit = 1; l = 0; while (limit < n + m - 1) { limit <<= 1; l ++; } // 计算位逆序 for (int i = 0; i < limit; i++) { r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1)); } // 分别在三个模数下计算卷积 cvlt(a1, b1, ans1, P1); cvlt(a2, b2, ans2, P2); cvlt(a3, b3, ans3, P3); // 输出结果 for (int i = 0; i < n + m - 1; i++) { LL res = crt(ans1[i], ans2[i], ans3[i]); cout << res << " "; } cout << "\n"; return 0; }
- 1
信息
- ID
- 3118
- 时间
- 5000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 12
- 已通过
- 2
- 上传者