多项式
用来放我的多项式板子。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4e5+10,mod=998244353;
typedef basic_string<int> poly;
int fac[N],inv[N];
poly tr;
int qpow(int x,int y)
{
int ret=1;
while(y)
{
if(y&1)
{
ret=ret*x%mod;
}
x=x*x%mod;
y/=2;
}
return ret;
}
void pre(int len)
{
fac[0]=1;
for(int i=1;i<=len;i++)
{
fac[i]=fac[i-1]*i%mod;
}
inv[len]=qpow(fac[len],mod-2);
for(int i=len-1;i>=0;i--)
{
inv[i]=inv[i+1]*(i+1)%mod;
}
}
poly ntt(poly ar,int fl)
{
int g=3,invg,len=ar.size();
invg=qpow(g,mod-2);
for(int i=0;i<len;i++)
{
if(tr[i]>i)
{
swap(ar[i],ar[tr[i]]);
}
}
for(int l=2;l<=len;l*=2)
{
int mid=l/2,W=qpow((fl==1? g:invg),(mod-1)/l),w=1;
for(int i=0;i+l<=len;i+=l)
{
for(int j=i,w0=w;j<i+mid;j++,w0=w0*W%mod)
{
int x=ar[j],y=w0*ar[j+mid]%mod;
ar[j]=(x+y);ar[j+mid]=(x-y+mod);
if(ar[j]>mod)
{
ar[j]-=mod;
}
if(ar[j+mid]>mod)
{
ar[j+mid]-=mod;
}
}
}
}
return ar;
}
poly mul(poly x,poly y)
{
int len=1;
while(len<x.size()+y.size())
{
len*=2;
}
x.resize(len);y.resize(len);
tr.resize(len);
tr[0]=0;
for(int i=1;i<len;i++)
{
tr[i]=(tr[i>>1]>>1)+(i%2)*len/2;
}
x=ntt(x,1);
y=ntt(y,1);
for(int i=0;i<len;i++)
{
x[i]=x[i]*y[i]%mod;
}
x=ntt(x,-1);
int iv=qpow(len,mod-2);
for(int i=0;i<len;i++)
{
x[i]=x[i]*iv%mod;
}
while(len>1)
{
if(x[len-1]!=0)
{
break;
}
len--;
}
x.resize(len);
return x;
}
poly getinv(poly ar)
{
int len=1,l2=ar.size();
poly b1,t1,t2;
while(len<l2)
{
len*=2;
}
ar.resize(len);b1.resize(1);
b1[0]=qpow(ar[0],mod-2);
for(int i=2;i<=len;i*=2)
{
t2=b1;
t2.resize(i);
for(int j=0;j<i/2;j++)
{
t2[j]=t2[j]*2%mod;
}
b1=mul(b1,b1);
t1=ar;
t1.resize(i);
b1=mul(b1,t1);
b1.resize(i);
for(int j=0;j<i;j++)
{
b1[j]=t2[j]-b1[j]+mod;
if(b1[j]>=mod)
{
b1[j]-=mod;
}
}
}
b1.resize(l2);
return b1;
}
poly getdao(poly ar,int x)
{
int len=ar.size()-x;
for(int i=0;i<len;i++)
{
ar[i]=ar[i+x]*fac[i+x]%mod*inv[i]%mod;
}
if(len)
{
ar.resize(len);
}else
{
ar.resize(1);
ar[0]=0;
}
return ar;
}
poly getji(poly ar,int x)
{
int len=ar.size()+x;
ar.resize(len);
for(int i=len-1;i>=x;i--)
{
ar[i]=ar[i-x]*inv[i]%mod*fac[i-x]%mod;
}
for(int i=0;i<x;i++)
{
ar[i]=0;
}
return ar;
}
poly getln(poly ar)
{
poly t1;
int len=ar.size();
t1=getdao(ar,1);
ar=getinv(ar);
ar=mul(ar,t1);
ar=getji(ar,1);
ar.resize(len);
return ar;
}
poly getexp(poly ar)
{
int len=1,l2=ar.size();
int l1=ar.size();
while(len<l1)
{
len*=2;
}
ar.resize(len);
poly t1,b1;
b1.resize(1);b1[0]=1;
for(int i=2;i<=len;i*=2)
{
t1=b1;
t1.resize(i);
t1=getln(t1);
for(int j=0;j<i;j++)
{
t1[j]=ar[j]-t1[j]+mod;
if(t1[j]>=mod)
{
t1[j]-=mod;
}
}
t1[0]++;
if(t1[0]>=mod)
{
t1[0]-=mod;
}
b1=mul(t1,b1);
b1.resize(i);
}
b1.resize(l1);
return b1;
}
poly getrev(poly x)
{
int len=x.size();
for(int i=0;i*2+1<len;i++)
{
swap(x[i],x[len-i-1]);
}
return x;
}
pair<poly,poly> getmod(poly x,poly y)
{
int l1=x.size(),l2=y.size();
if(l1<l2)
{
y.resize(1);
y[0]=0;
return make_pair(y,x);
}
int l3=l1-l2+1;
poly t1,t2;
t1=getrev(x);
t2=getrev(y);
t1.resize(l3);t2.resize(l3);
t2=getinv(t2);
t1=mul(t1,t2);
t1.resize(l3);
t1=getrev(t1);
y.resize(l2-1);
t2=t1;
if(l3>l2-1)
{
t2.resize(l2-1);
}
t2=mul(y,t2);
for(int i=0;i<l2-1;i++)
{
t2[i]=x[i]-t2[i]+mod;
if(t2[i]>=mod)
{
t2[i]-=mod;
}
}
t2.resize(l2-1);
return make_pair(t1,t2);
}
poly qp(poly x,int ts,poly y)
{
poly ret,tmp;
int len=y.size();
ret.resize(1);
ret[0]=1;
while(ts)
{
if(ts&1)
{
ret=mul(ret,x);
if(ret.size()>len*2)
{
ret.resize(len*2);
}
ret=getmod(ret,y).second;
}
x=mul(x,x);
if(x.size()>len*2)
{
x.resize(len*2);
}
x=getmod(x,y).second;
ts/=2;
}
return ret;
}

浙公网安备 33010602011771号