设 A A A为 n n n次多项式,考虑 A R ( x ) = x n A ( 1 x ) A_R(x) = x^n A(\frac 1 x) AR(x)=xnA(x1)
A R [ i ] = A [ n − i ] A_R[i] = A[n - i] AR[i]=A[n−i]
F ( x ) = Q ( x ) ∗ G ( x ) + R ( x ) F(x) = Q(x) * G(x) + R(x) F(x)=Q(x)∗G(x)+R(x)
F ( 1 x ) = Q ( 1 x ) ∗ G ( 1 x ) + R ( 1 x ) F(\frac 1 x) = Q(\frac 1 x) * G(\frac 1 x) + R(\frac 1 x) F(x1)=Q(x1)∗G(x1)+R(x1)
x n F ( 1 x ) = x n − m Q ( 1 x ) ∗ x m G ( 1 x ) + x n − m + 1 x m − 1 R ( 1 x ) 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) xnF(x1)=xn−mQ(x1)∗xmG(x1)+xn−m+1xm−1R(x1)
F R ( x ) = Q R ( x ) ∗ G R ( x ) + x n − m + 1 R R ( x ) F_R(x) = Q_R(x) * G_R(x) + x^{n-m+1}R_R(x) FR(x)=QR(x)∗GR(x)+xn−m+1RR(x)
F R ( x ) ≡ Q R ( x ) ∗ G R ( x ) m o d    x n − m + 1 F_R(x) \equiv Q_R(x) * G_R(x) \mod x^{n-m+1} FR(x)≡QR(x)∗GR(x)modxn−m+1
Q R ( x ) ≡ F R ( x ) ∗ G R − 1 ( x ) m o d    x n − m + 1 Q_R(x) \equiv F_R(x) * G_R^{-1} (x) \mod x^{n-m+1} QR(x)≡FR(x)∗GR−1(x)modxn−m+1
求出 G R G_R GR的逆,然后求出 Q R Q_R QR,再根据 R ( x ) = F ( x ) − Q ( x ) ∗ G ( x ) R(x) = F(x) - Q(x) * G(x) R(x)=F(x)−Q(x)∗G(x)求出 R ( x ) R(x) R(x)即可。
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char c; c = getchar() ;
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar() ;
return x * f ;
}
typedef long long ll ;
const int maxn = 1e6 + 10, mod = 998244353, g = 3;
int n, m, ginv, len ;
int a[maxn], b[maxn], F[maxn], G[maxn], Gr[maxn], Q[maxn], B[2][maxn] ;
ll power (ll x, int y) {
ll res = 1 ;
while (y) {
if (y & 1) res = res * x % mod ;
x = x * x % mod; y >>= 1 ;
}
return res ;
}
void ntt (int a[], int n, int f) {
for (int i = 0, j = 0; i < n; i ++) {
if (i > j) swap (a[i], a[j]) ;
for (int t = n >> 1; (j ^= t) < t; t >>= 1) ;
}
for (int i = 2; i <= n; i <<= 1) {
int wn = power (f ? ginv : g, (mod - 1) / i) ;
for (int j = 0; j < n; j += i)
for (int k = 0, w = 1; k < (i >> 1); k ++, w = 1ll * w * wn % mod) {
int A = a[j + k], B = 1ll * w * a[j + k + (i >> 1)] % mod ;
a[j + k] = (A + B) % mod; a[j + k + (i >> 1)] = (A - B + mod) % mod ;
}
}
if (f) {
int invn = power (n, mod - 2) ;
for (int i = 0; i < n; i ++) a[i] = 1ll * a[i] * invn % mod ;
}
}
void mul (int A[], int B[], int n) {
memset (a, 0, sizeof a) ;
memset (b, 0, sizeof b) ;
for (int i = 0; i < n / 2; i ++)
a[i] = A[i], b[i] = B[i] ;
ntt (a, n, 0); ntt (b, n, 0) ;
for (int i = 0; i < n; i ++) a[i] = 1ll * a[i] * b[i] % mod ;
ntt (a, n, 1) ;
for (int i = 0; i < n; i ++) A[i] = a[i] ;
}
void inv (int A[], int n) {
int cur = 0; len = 2 ;
B[cur][0] = power (A[0], mod - 2) ;
while (len <= (n << 1)) {
cur ^= 1; len <<= 1 ;
memset (B[cur], 0, sizeof B[cur]) ;
for (int i = 0; i <= len; i ++) B[cur][i] = 1ll * 2 * B[cur ^ 1][i] % mod ;
mul (B[cur ^ 1], B[cur ^ 1], len) ;
mul (B[cur ^ 1], A, len) ;
for (int i = 0; i <= len; i ++)
B[cur][i] = (B[cur][i] - B[cur ^ 1][i] + mod) % mod ;
}
for (int i = 0; i < len; i ++) A[i] = B[cur][i] ;
}
int main() {
//freopen("1.in", "r", stdin) ;
//freopen("1.out", "w", stdout) ;
ginv = power (g, mod - 2) ;
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) ;
mul (Q, Gr, len) ;
reverse (Q, Q + n - m + 1) ;
for (int i = 0; i < n - m + 1; i ++) printf("%d ", Q[i]) ;
printf("\n") ;
for (int i = n - m + 1; i <= n; i ++) Q[i] = 0 ;
while (len <= (n << 2)) len <<= 1 ;
mul (Q, G, len) ;
for (int i = 0; i < m; i ++) printf("%d ", (F[i] - Q[i] + mod) % mod) ;
printf("\n") ;
return 0 ;
}