P4512 【模板】多項式除法
阿新 • • 發佈:2019-01-18
ons 兩個 fin cap 題解 tchar tmp ack res 個整數,從低到高表示 \(G(x)\) 的各個系數。
\(\color{#0066ff}{數據範圍與提示}\)
\(\color{#0066ff}{ 題目描述 }\)
給定一個 \(n\) 次多項式 \(F(x)\) 和一個 \(m\) 次多項式 \(G(x)\) ,請求出多項式 \(Q(x)\), \(R(x)\),滿足以下條件:
- \(Q(x)\) 次數為 \(n-m\),\(R(x)\) 次數小於 \(m\)
- \(F(x) = Q(x) * G(x) + R(x)\)
所有的運算在模 \(998244353\) 意義下進行。
\(\color{#0066ff}{輸入格式}\)
第一行兩個整數 \(n\),\(m\),意義如上。
第二行 \(n+1\)個整數,從低到高表示 \(F(x)\) 的各個系數。 第三行 \(m+1\)
\(\color{#0066ff}{輸出格式}\)
第一行 \(n-m+1\) 個整數,從低到高表示 \(Q(x)\) 的各個系數。
第二行 \(m\) 個整數,從低到高表示 \(R(x)\) 的各個系數。 如果 \(R(x)\) 不足 \(m-1\) 次,多余的項系數補 \(0\)。
\(\color{#0066ff}{輸入樣例}\)
5 1
1 9 2 6 0 8
1 7
\(\color{#0066ff}{輸出樣例}\)
237340659 335104102 649004347 448191342 855638018
760903695
\(\color{#0066ff}{數據範圍與提示}\)
對於所有數據,\(1 \le m < n \le 10^5\),給出的系數均屬於 \([0, 998244353) \cap \mathbb{Z}\)
\(\color{#0066ff}{ 題解 }\)
以下圖片來自ghj1222的課件qwq
#include<bits/stdc++.h> #define LL long long LL in() { char ch; LL x = 0, f = 1; while(!isdigit(ch = getchar()))(ch == '-') && (f = -f); for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48)); return x * f; } const int maxn = 4e5 + 10; const int mod = 998244353; int len, r[maxn]; using std::vector; LL ksm(LL x, LL y) { LL re = 1LL; while(y) { if(y & 1) re = re * x % mod; x = x * x % mod; y >>= 1; } return re; } void FNTT(vector<int> &A, int flag) { A.resize(len); for(int i = 0; i < len; i++) if(i < r[i]) std::swap(A[i], A[r[i]]); for(int l = 1; l < len; l <<= 1) { int w0 = ksm(3, (mod - 1) / (l << 1)); for(int i = 0; i < len; i += (l << 1)) { int w = 1, a0 = i, a1 = i + l; for(int k = 0; k < l; k++, a0++, a1++, w = 1LL * w * w0 % mod) { int tmp = 1LL * A[a1] * w % mod; A[a1] = ((A[a0] - tmp) % mod + mod) % mod; A[a0] = (A[a0] + tmp) % mod; } } } if(!(~flag)) { std::reverse(A.begin() + 1, A.end()); int inv = ksm(len, mod - 2); for(int i = 0; i < len; i++) A[i] = 1LL * A[i] * inv % mod; } } vector<int> operator - (const vector<int> &A, const vector<int> &B) { vector<int> ans; for(int i = 0; i < (int)std::min(A.size(), B.size()); i++) ans.push_back(A[i] - B[i]); if(A.size() < B.size()) for(int i = A.size(); i < (int)B.size(); i++) ans.push_back(-B[i]); if(A.size() > B.size()) for(int i = B.size(); i < (int)A.size(); i++) ans.push_back(A[i]); return ans; } vector<int> operator * (vector<int> A, vector<int> B) { int tot = A.size() + B.size() - 1; for(len = 1; len <= tot; len <<= 1); for(int i = 0; i < len; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) * (len >> 1)); FNTT(A, 1), FNTT(B, 1); vector<int> ans; for(int i = 0; i < len; i++) ans.push_back(1LL * A[i] * B[i] % mod); FNTT(ans, -1); ans.resize(tot); return ans; } vector<int> inv(const vector<int> &A) { if(A.size() == 1) { vector<int> ans; ans.push_back(ksm(A[0], mod - 2)); return ans; } int n = A.size(), _ = (n + 1) >> 1; vector<int> ans, B = A; B.resize(_); ans.push_back(2); B = inv(B); ans = B * (ans - A * B); ans.resize(n); return ans; } vector<int> rev(const vector<int> &A) { vector<int> B = A; std::reverse(B.begin(), B.end()); return B; } void work(vector<int> f, vector<int> g) { int n = f.size() - 1, m = g.size() - 1; vector<int> ff = rev(f), gg = rev(g), s, y; ff.resize(n - m + 1), gg.resize(n - m + 1); s = ff * inv(gg); s.resize(n - m + 1); s = rev(s); vector<int> v = g * s; v.resize(m), f.resize(m), y.resize(m); for(int i = 0; i < m; i++) y[i] = ((f[i] - v[i]) % mod + mod) % mod; for(int i = 0; i < n - m + 1; i++) printf("%d%c", s[i], i == n - m? '\n' : ' '); for(int i = 0; i < m; i++) printf("%d%c", y[i], i == m - 1? '\n' : ' '); } int main() { int n = in(), m = in(); vector<int> a, b; for(int i = 0; i <= n; i++) a.push_back(in()); for(int i = 0; i <= m; i++) b.push_back(in()); work(a, b); return 0; }
P4512 【模板】多項式除法