Problem Description
$ $ A given n-order polynomial $ F (x) $ and $ m $ a polynomial of degree $ G (x) $, requesting the polynomial $ Q (x) $, $ R (x) $, satisfying the following conditions:
- $ Q (x) $ is the number of $ nm $, $ R (x) $ $ m $ times less than
- $F(x) = Q(x) * G(x) + R(x)$
All operations carried out in the sense die 998 244 353
See Los Valley P4512
analysis
Specifically, provided is a polynomial $ A $ $ $ n-order polynomial, R & lt consider a $ $ operation, such that
$\displaystyle A_R(x)=x^n A(\frac{1}{x})$
Imagine a little, can be found in $ A_R [i] = A [ni] $ ($ [i] $ I $ polynomial representing the first-order coefficients $).
This operation can be $ O (n) $ completed.
Then start of the formula.
$$F(x)=Q(x) * G(x)+R(x)$$
$$\displaystyle F(\frac{1}{x})=Q(\frac{1}{x}) * G(\frac{1}{x})+R(\frac{1}{x})$$
$$\displaystyle x^n F(\frac{1}{x})=x^{n-m} Q(\frac{1}{x}) * x^m G(\frac{1}{x})+x^{n-m+1} * x^{m-1} R(\frac{1}{x})$$
$$\displaystyle F_R(x)=Q_R(x)*G_R(x)+x^{n-m+1} * R_R(x)$$
$$\displaystyle F_R(x) \equiv Q_R(x)*G_R(x)\pmod {x^{n-m+1}}$$
$$\displaystyle Q_R(x) \equiv F_R(x)*G_R^{-1}(x)\pmod {x^{n-m+1}}$$
$ G_R $ inverse demand again, and then we can use polynomial multiplication obtained $ Q $. then
$$R(x)=F(x)-G(x)*Q(x)$$
It can be calculated directly. Flip coefficient can be with their own $ reverse $ functions, inverse of the best iterative solver .
The total time complexity $ O (nlogn) $.
Code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1<<20; int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = (x<<1) + (x<<3) + c - '0', c = getchar(); return x * f; } namespace Polynomial { const ll P = 998244353, g = 3, gi = 332748118; static int rev[N]; int lim, bit; ll add(ll a, ll b) { return (a += b) >= P ? a - P : a; } ll qpow(ll a, ll b) { ll prod = 1; while(b) { if(b & 1) prod = prod * a % P; a = a * a % P; b >>= 1; } return (prod + P) % P; } void calrev() { for(int i = 1; i < lim; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1)); } void NTT(ll *A, int inv) { for(int i = 0; i < lim; i++) if(i < rev[i]) swap(A[i], A[rev[i]]); for(int mid = 1; mid < lim; mid <<= 1) { ll tmp = qpow(inv == 1 ? g : gi, (P - 1) / (mid << 1)); for(int j = 0; j < lim; j += (mid << 1)) { ll omega = 1; for(int k = 0; k < mid; k++, omega = (omega * tmp) % P) { int x = A[j + k], y = omega * A[j + k + mid] % P; A[j + k] = (x + y) % P; A[j + k + mid] = (x - y + P) % P; } } } if(inv == 1) return; int invn = qpow(lim, P - 2); for(int i = 0; i < lim; i++) A[i] = A[i] * invn % P; } static ll x[N], y[N]; void mul(ll *a, ll *b) { memset(x, 0, sizeof x); memset(y, 0, sizeof y); for(int i = 0; i < (lim >> 1); i++) x[i] = a[i], y[i] = b[i]; NTT(x, 1), NTT(y, 1); for(int i = 0; i < lim; i++) x[i] = x[i] * y[i] % P; NTT(x, -1); for(int i = 0; i < lim; i++) a[i] = x[i]; } static ll c[2][N]; void Inv(ll *a, int n) { int p = 0; memset(c, 0, sizeof c); c[0][0] = qpow(a[0], P - 2); lim = 2, bit = 1; while(lim <= (n << 1)) { lim <<= 1, bit++; calrev(); p ^= 1; memset(c[p], 0, sizeof c[p]); for(int i = 0; i <= lim; i++) c[p][i] = add(c[p^1][i], c[p^1][i]); mul(c[p^1], c[p^1]); mul(c[p^1], a); for(int i = 0; i <= lim; i++) c[p][i] = add(c[p][i], P - c[p^1][i]); } for(int i = 0; i < lim; i++) a[i] = c[p][i]; } } using namespace Polynomial; int n, m; ll F[N], G[N], Q[N], R[N], Gr[N]; int main() { n = read(), m = read(); for(int i = 0; i <= n; i++) F[i] = read(), Q[n - i] = F[i]; for(int i = 0; i <= m; i++) G[i] = read(), Gr[m - i] = G[i]; for(int i = n - m + 2; i <= m; i++) Gr[i] = 0; Inv(Gr, n - m + 1); //Gr=Gr的逆 mul(Q, Gr); //Q=Q*Gr reverse(Q, Q + n - m + 1); //Q=reverse(Q) for(int i = n - m + 1; i <= n; i++) Q[i] = 0; for(int i = 0; i <= n - m; i++) printf("%lld ", Q[i]); printf("\n"); lim = 1, bit = 0; while(lim <= (n << 2)) lim <<= 1, bit++; calrev(); mul(Q, G); for(int i = 0; i < m; i++) printf("%lld ", add(F[i], P - Q[i])); //R=F - Q*G return 0; }
Code Reprinted from: https://www.luogu.org/blog/AKIOIorz/p4512-mu-ban-duo-xiang-shi-chu-fa