在摸索了很久很久,还是没找到多项式的正确入门方式,所以尝试着自己写一下
void mul(LL* a,int n, LL* b,int m){
for(int i=n+1; i<=Lim; i++) a[i] = 0;
for(int i=m+1; i<=Lim; i++) b[i] = 0;
for(int i=0; i<=n; i++) a[i] = (a[i]%P + P) % P; // 第一个多项式系数
for(int i=0; i<=m; i++) b[i] = (b[i]%P + P) % P; // 第二个多项式系数
NTT(a,1); NTT(b,1);
for(int i=0; i<= Lim; i++) a[i] = a[i]*b[i] % P; // O(n)求点值表示法
NTT(a,-1); // 逆变换变成系数表示法
}
// A的逆存在B中
void get_inv(int n,LL *a,LL *b,LL mod){
if (n == 1) { b[0] = qpow(a[0],mod-2); return;}
get_inv((n + 1)/2,a,b,mod);
int len = 0,lim = 1;
while(lim < (n << 1)) lim <<= 1, ++len;
for(int i=1; i<lim; i++) r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
for(int i=0; i<n; i++) c[i] = a[i];
for(int i=n; i<lim; i++) c[i] = 0;
NTT(c,lim,1); NTT(b,lim,1);
for(int i=0; i<lim; i++)
b[i] = (2ll-c[i]*b[i]%mod+mod)%mod*b[i]%mod;
NTT(b,lim,-1);
for(int i=n; i<lim; i++) b[i] = 0;
}
#include
using namespace std;
typedef long long LL;
inline long long read(){
long long f = 1, x = 0;char ch = getchar();
while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
const int maxn = 4e5 + 10;
const LL mod = 998244353, G = 3;
LL f[maxn],g[maxn],fr[maxn],gr[maxn],q[maxn],rs[maxn];
namespace Poly{
LL c[maxn],r[maxn],x[maxn];
LL qpow(LL a,LL b){
LL base = a % mod,ans = 1;
while(b){
if (b & 1) ans = ans*base % mod;
base = base * base % mod;
b >>= 1;
}
return ans % mod;
}
inline void NTT(LL *A,int Lim,int type){
for(int i=0; i<Lim; i++)
if (i < r[i]) swap(A[i],A[r[i]]);
for(int m = 1; m < Lim; m<<=1){
LL wn = qpow(G, (mod-1)/(m << 1));
for(int j=0; j<Lim; j+=(m<<1)){
LL w = 1;
for(int k=0; k<m; k++,w = w*wn % mod){
LL x = A[j+k],y = w*A[j+k+m] % mod;
A[j+k] = (x + y) % mod;
A[j+k+m] = (x - y + mod) % mod;
}
}
}
if (type == 1) return;
LL inv = qpow(Lim,mod-2); reverse(A+1,A+Lim);
for(int i=0; i<Lim; i++) A[i] = A[i]*inv % mod;
}
void init(){
memset(c,0,sizeof(c));
memset(r,0,sizeof(r));
}
void mul(LL* a, LL* b,int lim){
memset(x,0,sizeof(x));
for(int i=0; i<(lim >> 1); i++) x[i] = (b[i] % mod + mod) % mod;
NTT(a, lim, 1); NTT(x, lim,1);
for(int i=0; i<lim; i++) a[i] = a[i] * x[i] % mod;
NTT(a, lim, -1);
}
// A的逆存在B中
void get_inv(int n,LL *a,LL *b,LL mod){
if (n == 1) { b[0] = qpow(a[0],mod-2); return;}
get_inv((n + 1)/2,a,b,mod);
int len = 0,lim = 1;
while(lim < (n << 1)) lim <<= 1, ++len;
for(int i=1; i<lim; i++) r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
for(int i=0; i<n; i++) c[i] = a[i];
for(int i=n; i<lim; i++) c[i] = 0;
NTT(c,lim,1); NTT(b,lim,1);
for(int i=0; i<lim; i++)
b[i] = (2ll-c[i]*b[i]%mod+mod)%mod*b[i]%mod;
NTT(b,lim,-1);
for(int i=n; i<lim; i++) b[i] = 0;
}
// f(x) = q(x) * g(x) + r(x)
void get_div(LL f[],int n,LL g[],int m,LL q[],LL rs[]){
for(int i=0; i<=n; i++) fr[i] = f[n-i];
for(int i=0; i<=m; i++) gr[i] = g[m-i];
for(int i=n-m+2; i<=m; i++) gr[i] = 0;
get_inv(n-m+1, gr, q, mod);
int len = 0,lim = 1;
while(lim <= (n << 1)) lim <<= 1, ++len;
for(int i=1; i<=lim; i++) r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
mul(q, fr, lim);
reverse(q,q+n-m+1);
for(int i=n-m+1; i<=n; i++) q[i] = 0;
mul(g, q, lim);
for(int i=0; i<=m; i++) rs[i] = (f[i] - g[i] + mod) % mod;
}
}
int main(){
int n = read(),m = read();
for(int i=0; i<=n; i++) f[i] = read();
for(int i=0; i<=m; i++) g[i] = read();
Poly::get_div(f,n,g,m,q,rs);
for(int i=0; i<=n-m; i++) printf("%d ",q[i]); printf("\n");
for(int i=0; i<=m-1; i++) printf("%d ",rs[i]); printf("\n");
return 0;
}