R(x)R(x)R(x)是一个n−mn - mn−m阶多项式,Q(x)Q(x)Q(x)是一个小于mmm阶的多项式。 有F(x)≡R(x)G(x)+Q(x)(modxn+1)F(1x)≡R(1x)G(1x)+Q(1x)(modxn+1)同时乘上一个xn,Frev(x)≡(xmRrev(x))(xn−mGrev(x))+xn−degQQrev(x)(modxn+1)Frev(x)≡Rrev(x)Grev(x)+Qrev(x)xn−degQ(modxn+1)有degQ<m,n−degQ>=n−m+1,所以有Frev(x)≡Rrev(x)Grev(x)(modxn−m+1)有F(x) \equiv R(x) G(x) + Q(x) \pmod{x ^ {n + 1}}\\ F(\frac{1}{x}) \equiv R(\frac{1}{x})G(\frac{1}{x}) + Q(\frac{1}{x}) \pmod {x ^{n + 1}}\\ 同时乘上一个x ^ n, F^{rev}(x) \equiv \left(x ^m R ^{rev}(x)\right) \left(x ^{n - m}G ^{rev}(x)\right) + x ^{n - deg_Q} Q ^{rev} (x) \pmod{x ^{n + 1}} \\ F^{rev}(x) \equiv R^{rev}(x) G^{rev}(x) + Q^{rev}(x) x ^{n - deg_Q}\pmod{x ^{n + 1}}\\ 有deg_Q < m, n - deg_Q >= n - m + 1,所以有F^{rev}(x) \equiv R^{rev}(x) G^{rev}(x) \pmod{x ^{n - m + 1}}\\ 有F(x)≡R(x)G(x)+Q(x)(modxn+1)F(x1)≡R(x1)G(x1)+Q(x1)(modxn+1)同时乘上一个xn,Frev(x)≡(xmRrev(x))(xn−mGrev(x))+xn−degQQrev(x)(modxn+1)Frev(x)≡Rrev(x)Grev(x)+Qrev(x)xn−degQ(modxn+1)有degQ<m,n−degQ>=n−m+1,所以有Frev(x)≡Rrev(x)Grev(x)(modxn−m+1) 只要多项式求逆,即可得到R(x)R(x)R(x),然后代入原式求得Q(x)Q(x)Q(x)。
#include<bits/stdc++.h>usingnamespace std;constint mod =998244353, inv2 = mod +1>>1;namespace Quadratic_residue {struct Complex {int r, i;Complex(int _r =0,int _i =0):r(_r),i(_i){}};int I2;Complex operator*(const Complex &a, Complex &b){returnComplex((1ll* a.r * b.r % mod +1ll* a.i * b.i % mod * I2 % mod)% mod,(1ll* a.r * b.i % mod +1ll* a.i * b.r % mod)% mod);}Complex quick_pow(Complex a,int n){Complex ans =Complex(1,0);while(n){if(n &1){ans = ans * a;}a = a * a;n >>=1;}return ans;}intget_residue(int n){mt19937 e(233);if(n ==0){return0;}if(quick_pow(n,(mod -1)>>1).r == mod -1){return-1;}uniform_int_distribution<int>r(0, mod -1);int a =r(e);while(quick_pow((1ll* a * a % mod - n + mod)% mod,(mod -1)>>1).r ==1){a =r(e);}I2 =(1ll* a * a % mod - n + mod)% mod;int x =quick_pow(Complex(a,1),(mod +1)>>1).r, y = mod - x;if(x > y)swap(x, y);return x;}}constint N =6e5+10;int r[N], inv[N], b[N], c[N], d[N], e[N], t[N];intquick_pow(int a,int n){int ans =1;while(n){if(n &1){ans =1ll* a * ans % mod;}a =1ll* a * a % mod;n >>=1;}return ans;}voidget_r(int lim){for(int i =0; i < lim; i++){r[i]=(i &1)*(lim >>1)+(r[i >>1]>>1);}}voidget_inv(int n){inv[1]=1;for(int i =2; i <= n; i++){inv[i]=1ll*(mod - mod / i)* inv[mod % i]% mod;}}voidNTT(int*f,int lim,int rev){for(int i =0; i < lim; i++){if(i < r[i]){swap(f[i], f[r[i]]);}}for(int mid =1; mid < lim; mid <<=1){int wn =quick_pow(3,(mod -1)/(mid <<1));for(int len = mid <<1, cur =0; cur < lim; cur += len){int w =1;for(int k =0; k < mid; k++, w =1ll* w * wn % mod){int x = f[cur + k], y =1ll* w * f[cur + mid + k]% mod;f[cur + k]=(x + y)% mod, f[cur + mid + k]=(x - y + mod)% mod;}}}if(rev ==-1){int inv =quick_pow(lim, mod -2);reverse(f +1, f + lim);for(int i =0; i < lim; i++){f[i]=1ll* f[i]* inv % mod;}}}voidpolyinv(int*f,int*g,int n){if(n ==1){g[0]=quick_pow(f[0], mod -2);return;}polyinv(f, g, n +1>>1);for(int i =0; i < n; i++){t[i]= f[i];}int lim =1;while(lim <2* n){lim <<=1;}get_r(lim);NTT(t, lim,1);NTT(g, lim,1);for(int i =0; i < lim; i++){int cur =(2-1ll* g[i]* t[i]% mod + mod)% mod;g[i]=1ll* g[i]* cur % mod;t[i]=0;}NTT(g, lim,-1);for(int i = n; i < lim; i++){g[i]=0;}}voidpolysqrt(int*f,int*g,int n){if(n ==1){g[0]= Quadratic_residue::get_residue(f[0]);return;}polysqrt(f, g, n +1>>1);polyinv(g, b, n);int lim =1;while(lim <2* n){lim <<=1;}get_r(lim);for(int i =0; i < n; i++){t[i]= f[i];}NTT(g, lim,1);NTT(b, lim,1);NTT(t, lim,1);for(int i =0; i < lim; i++){g[i]=(1ll* inv2 * g[i]% mod +1ll* inv2 * b[i]% mod * t[i]% mod)% mod;b[i]= t[i]=0;}NTT(g, lim,-1);for(int i = n; i < lim; i++){g[i]=0;}}voidderivative(int*a,int*b,int n){for(int i =0; i < n; i++){b[i]=1ll* a[i +1]*(i +1)% mod;}}voidintegrate(int*a,int n){for(int i = n -1; i >=1; i--){a[i]=1ll* a[i -1]* inv[i]% mod;}a[0]=0;}voidpolyln(int*f,int*g,int n){polyinv(f, b, n);derivative(f, g, n);int lim =1;while(lim <2* n){lim <<=1;}get_r(lim);NTT(g, lim,1);NTT(b, lim,1);for(int i =0; i < lim; i++){g[i]=1ll* g[i]* b[i]% mod;b[i]=0;}NTT(g, lim,-1);for(int i = n; i < lim; i++){g[i]=0;}integrate(g, n);}voidpolyexp(int*f,int*g,int n){if(n ==1){g[0]=1;return;}polyexp(f, g, n +1>>1);int lim =1;while(lim <2* n){lim <<=1;}polyln(g, d, n);for(int i =0; i < n; i++){t[i]=(f[i]- d[i]+ mod)% mod;}t[0]=(t[0]+1)% mod;get_r(lim);NTT(g, lim,1);NTT(t, lim,1);for(int i =0; i < lim; i++){g[i]=1ll* g[i]* t[i]% mod;t[i]= d[i]=0;}NTT(g, lim,-1);for(int i = n; i < lim; i++){g[i]=0;}}/*b存放多项式逆,c存放多项式开根,d存放多项式对数ln,e存放多项式指数exp,t作为中间转移数组,如果要用到polyinv,得提前调用get_inv(n)先预先得到我们想要得到的逆元范围。
*/int f[N], fr[N], g[N], gr[N], rr[N], n, m;intmain(){// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);scanf("%d %d",&n,&m);for(int i =0; i <= n; i++){scanf("%d",&f[i]);fr[n - i]= f[i];}for(int i =0; i <= m; i++){scanf("%d",&g[i]);gr[m - i]= g[i];}for(int i = n - m +1; i <= n; i++){fr[i]= gr[i]=0;}polyinv(gr, b, n - m +1);for(int i =0; i < n - m +1; i++){gr[i]= b[i];b[i]=0;}int lim =1;while(lim <2*(n - m +1)){lim <<=1;}get_r(lim);NTT(fr, lim,1);NTT(gr, lim,1);for(int i =0; i < lim; i++){fr[i]=1ll* fr[i]* gr[i]% mod;}NTT(fr, lim,-1);for(int i =0; i <= n - m; i++){rr[i]= fr[n - m - i];}for(int i =0; rr[i]; i++){printf("%d ", rr[i]);}puts("");lim =1;while(lim <=2* n){lim <<=1;}get_r(lim);NTT(rr, lim,1);NTT(g, lim,1);for(int i =0; i < lim; i++){g[i]=1ll* g[i]* rr[i]% mod;}NTT(g, lim,-1);for(int i =0; i < m; i++){f[i]=(f[i]- g[i]+ mod)% mod;}for(int i =0; i < m; i++){printf("%d ", f[i]);}puts("");return0;}