P4238 【模板】多项式求逆
题意:
数据范围
1
≤
n
≤
1
0
5
1\leq n\leq 10^5
1≤n≤105
1
≤
a
i
≤
1
0
9
1\leq a_i\leq 10^9
1≤ai≤109
题解:
f
∗
g
≡
1
(
m
o
d
x
n
)
f*g\equiv1(\mod x^n)
f∗g≡1(modxn)
设
f
∗
a
≡
1
(
m
o
d
x
n
2
)
f*a\equiv1(\mod x^{\frac n 2})
f∗a≡1(modx2n)
g
−
a
≡
0
(
m
o
d
x
n
2
)
g-a\equiv0(\mod x^{\frac n 2})
g−a≡0(modx2n)
(
g
−
a
)
2
≡
0
(
m
o
d
x
n
)
(g-a)^2\equiv0(\mod x^n)
(g−a)2≡0(modxn)
g
2
+
a
2
−
2
a
g
≡
0
(
m
o
d
x
n
)
g^2+a^2-2ag\equiv0(\mod x^n)
g2+a2−2ag≡0(modxn)
两边同乘
f
f
f得
g
+
a
2
f
−
2
a
≡
0
(
m
o
d
x
n
)
g+a^2f-2a\equiv0(\mod x^n)
g+a2f−2a≡0(modxn)
g
=
2
a
−
a
2
f
(
m
o
d
x
n
)
g=2a-a^2f(\mod x^n)
g=2a−a2f(modxn)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
#define ll long long
const int mod=998244353;
int a[N<<2],b[N<<2],rev[N<<2],limit,lim;
int f[N<<2],g[N<<2];
int n;
int poww(int a,int b,int c){
int ans=1,base=a;
while(b){
if(b&1)ans=1ll*ans*base%c;
base=1ll*base*base%c;
b>>=1;
}
return ans;
}
void fft(int *a,int type){
for(int i=0;i<limit;i++)if(rev[i]>i)swap(a[i],a[rev[i]]);
for(int mid=1;mid<limit;mid<<=1){
int wn=poww(3,type==1?(mod-1)/(mid<<1):(mod-1-(mod-1)/(mid<<1)),mod);
for(int i=0;i<limit;i+=(mid<<1)){
int w=1;
for(int j=0;j<mid;j++,w=1ll*w*wn%mod){
int x=a[i+j],y=1ll*w*a[i+j+mid]%mod;
a[i+j]=(x+y)%mod,a[i+j+mid]=(x+mod-y)%mod;
}
}
}
if(type==-1){
int inv=poww(limit,mod-2,mod);
for(int i=0;i<limit;i++)a[i]=1ll*a[i]*inv%mod;
}
}
void solve(int n,int *f,int *g){
if(n==1){
g[0]=poww(f[0],mod-2,mod);
return;
}
solve((n+1)/2,f,g);
limit=1,lim=0;
while(limit<(n<<1))limit<<=1,lim++;
for(int i=0;i<limit;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lim-1)),a[i]=b[i]=0;
for(int i=0;i<n;i++)a[i]=f[i],b[i]=g[i];
fft(a,1),fft(b,1);
for(int i=0;i<limit;i++)a[i]=1ll*b[i]*((2ll-1ll*b[i]*a[i]%mod+mod)%mod)%mod;
fft(a,-1);
for(int i=0;i<n;i++)g[i]=a[i];//注意这里是n不是limit
}
int main(){
// freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=0;i<n;i++)cin>>f[i];
solve(n,f,g);
for(int i=0;i<n;i++)cout<<g[i]<<" ";cout<<endl;
return 0;
}