P4512 [template] polynomial division
Title 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 mold $ 998,244,353 $ significance.
Input and output formats
Input formats:The first line of two integers $ n $, $ m $, meaning as above.
The second row $ n + 1 $ integers represented from low to high $ F (x) $ of each coefficient.
The third row $ m + 1 $ integers from low to high each coefficient represents $ G (x) $ a.
The first row $ n-m + 1 $ integers from low to high each coefficient represents $ Q (x) $ a.
The second row $ m $ integers, each represented from low to high coefficient $ R (x) $ a.
If $ R (x) is less than $ $ m-1 $ times excess coefficient complement $ 0 $.
Sample input and output
5 1 1 9 2 6 0 8 1 7
237340659 335104102 649004347 448191342 855638018 760903695
Explanation
For all data, $ 1 \ le m <n \ le 10 ^ 5 $, analysis coefficients belong $ [0, 998244353) \ cap \ mathbb {Z} $.
answer
Still dealing with borders.
\ [F_R (x) \ equiv
(q_R \ times g_R) (x) \ mod x ^ {n-m + 1} \] After inversion, because the original equation, it can only take \ (n-m + 1 \) key. \ (G \) before inverse relation Reserved \ (n-m + 1 \ ) items.
\ [Q_R (x) \ equiv
(f_R \ times g_R ^ {- 1}) (x) \ mod x ^ {n-m + 1} \] and \ (Q_R \) flipped about get \ (Q \) . Back substitution \ (r (x) = f (x) - (q \ times g) (x) \) can be solved \ (R & lt \) , just before the count \ (m \) keys to.
\(T(n)=O(n\log n)\)
#include<bits/stdc++.h>
#define il inline
#define co const
template<class T>T read(){
T data=0,w=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(T&x) {return x=read<T>();}
typedef long long LL;
using namespace std;
typedef vector<int> polynomial;
co int mod=998244353,g=3,g_inv=332748118;
il int add(int a,int b){
return (a+=b)>=mod?a-mod:a;
}
il int mul(int a,int b){
return (LL)a*b%mod;
}
int fpow(int a,int b){
int ans=1;
for(;b;b>>=1,a=mul(a,a))
if(b&1) ans=mul(ans,a);
return ans;
}
void num_trans(polynomial&a,int inverse){
int limit=a.size(),len=log2(limit);
static vector<int> bit_rev;
if(bit_rev.size()!=limit){
bit_rev.resize(limit);
for(int i=0;i<limit;++i) bit_rev[i]=bit_rev[i>>1]>>1|(i&1)<<(len-1);
}
for(int i=0;i<limit;++i)if(i<bit_rev[i]) swap(a[i],a[bit_rev[i]]);
for(int step=1;step<limit;step<<=1){
int gn=fpow(inverse==1?g:g_inv,(mod-1)/(step<<1));
for(int even=0;even<limit;even+=step<<1){
int odd=even+step,gk=1;
for(int k=0;k<step;++k,gk=mul(gk,gn)){
int t=mul(gk,a[odd+k]);
a[odd+k]=add(a[even+k],mod-t),a[even+k]=add(a[even+k],t);
}
}
}
if(inverse==-1){
int lim_inv=fpow(limit,mod-2);
for(int i=0;i<limit;++i) a[i]=mul(a[i],lim_inv);
}
}
polynomial poly_inv(polynomial a,int n){
polynomial b[2];
b[0].push_back(fpow(a[0],mod-2));
if(n==1) return b[0]; // edit 2
a.resize(1<<int(ceil(log2(n))+1));
int limit,len;
for(limit=2,len=1;limit<n;limit<<=1,++len){
polynomial a1(a.begin(),a.begin()+limit);
a1.resize(limit<<1),num_trans(a1,1);
b[(len&1)^1].resize(limit<<1),num_trans(b[(len&1)^1],1);
b[len&1].resize(limit<<1);
for(int i=0;i<limit<<1;++i) b[len&1][i]=mul(add(2,mod-mul(a1[i],b[(len&1)^1][i])),b[(len&1)^1][i]);
num_trans(b[len&1],-1),b[len&1].resize(limit);
}
assert(a.size()==limit<<1),num_trans(a,1);
b[(len&1)^1].resize(limit<<1),num_trans(b[(len&1)^1],1);
b[len&1].resize(limit<<1);
for(int i=0;i<limit<<1;++i) b[len&1][i]=mul(add(2,mod-mul(a[i],b[(len&1)^1][i])),b[(len&1)^1][i]);
num_trans(b[len&1],-1),b[len&1].resize(n);
return b[len&1];
}
polynomial poly_div(polynomial f,polynomial g){ // return the quotient
int n=f.size()-1,m=g.size()-1;
reverse(g.begin(),g.end()),g.resize(n-m+1),g=poly_inv(g,n-m+1); // edit 1:access partially
reverse(f.begin(),f.end()),f.resize(n-m+1);
int limit=1<<int(ceil(log2(2*(n-m)+1)));
f.resize(limit),g.resize(limit);
num_trans(f,1),num_trans(g,1);
for(int i=0;i<limit;++i) f[i]=mul(f[i],g[i]);
num_trans(f,-1),f.resize(n-m+1);
return reverse(f.begin(),f.end()),f;
}
int main(){
// freopen("LG4512.in","r",stdin);
int n=read<int>(),m=read<int>();
polynomial f(n+1),g(m+1);
for(int i=0;i<=n;++i) read(f[i]);
for(int i=0;i<=m;++i) read(g[i]);
polynomial q=poly_div(f,g);
for(int i=0;i<=n-m;++i) printf("%d ",q[i]);
puts("");
// poly_mod
int limit=1<<int(ceil(log2(n)));
g.resize(limit),q.resize(limit);
num_trans(g,1),num_trans(q,1);
for(int i=0;i<limit;++i) g[i]=mul(g[i],q[i]);
num_trans(g,-1);
for(int i=0;i<m;++i) printf("%d ",add(f[i],mod-g[i]));
return 0;
}