模板直接到最底下
多項式求逆
給定求
使用倍增構造。
若n=1,則直接求0次項的乘法逆元。
若n>1
設滿足
遞歸即可,複雜度
多項式除法
已知,它們的次數分別爲
求是除法,是取模,其中的係數不大於,的係數小於
首先可以發現就是將A的係數翻轉過來。
同乘
那麼
將這個東西,可以發現對的係數不會有影響。
於是
於是多項式求逆,然後乘起來就沒了。
多項式取模
先除,再乘,再減,就沒了。
多項式開方
給定求
使用倍增構造。
當n=1時,相當於求0次項的二次剩餘。
(然而我並不會二次剩餘,而且很多題裏的常數項是真的常數,所以這裏忽略二次剩餘)
當n>1時,
設滿足
兩邊平方
因爲
求逆然後乘一乘,加一加就行了。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 3201000
#define ll long long
#define mo 998244353
using namespace std;
int n,m;
ll D[N],W[N],A[N],B[N],C[N],E[N],len,a[N],b[N],c[N];
ll mi(ll a,ll b)
{
a%=mo;ll jy=1;
for(;b;b/=2,a=a*a%mo) if(b%2==1) jy=jy*a%mo;
return jy;
}
void DFT(ll *a,int sig,int deg)
{
int len,lg;
for(len=1,lg=0;len<=deg;len*=2,lg++);
W[0]=1;W[1]=mi(3,(mo-1)/len);fo(i,2,len) W[i]=W[i-1]*W[1]%mo;
fo(i,0,len-1)
{
int p=0;
for(int j=0,tp=i;j<lg;j++,tp/=2) p=(p<<1)+(tp%2);
D[p]=a[i];
}
for(int m=2;m<=len;m*=2)
{
int half=m/2,tmp=len/m;
for(int j=0;j<len;j+=m)
{
fo(i,j,j+half-1)
{
ll u=D[i],v=D[i+half]*((sig==1)?W[(i-j)*tmp]:W[len-(i-j)*tmp])%mo;
D[i]=(u+v)%mo;
D[i+half]=(u-v+mo)%mo;
}
}
}
if(sig==-1)
{
ll inv=mi(len,mo-2);
fo(i,0,len-1) D[i]=D[i]*inv%mo;
}
fo(i,0,len-1) a[i]=D[i];
}
void poly_inv(ll *a,ll *b,int deg)
{
if(deg==1)
{
b[0]=mi(a[0],mo-2);
b[1]=0;
return;
}
poly_inv(a,b,(deg+1)/2);
fo(i,0,deg-1) A[i]=a[i],B[i]=b[i];
fo(i,deg,deg+deg-1) A[i]=B[i]=0;
DFT(A,1,deg);DFT(B,1,deg);
fo(i,0,deg+deg-1) A[i]=(A[i]*B[i]%mo*B[i]%mo)%mo;
DFT(A,-1,deg);
fo(i,0,deg-1) b[i]=(b[i]*2ll-A[i]+mo)%mo;
fo(i,deg,deg+deg) b[i]=0;
}
void poly_divide(ll *a,int n,ll *b,int m,ll *c)
{
int len=1;
for(;len<n-m+1;len*=2);
fo(i,0,m-1) c[i]=b[m-i-1],C[i]=0;
fo(i,min(m,n-m+1),len+len) c[i]=C[i]=0;
poly_inv(c,C,len);
fo(i,0,n-1) A[i]=a[n-i-1];
fo(i,n-m+1,len+len) A[i]=C[i]=0;
DFT(A,1,len);DFT(C,1,len);
fo(i,0,len+len) A[i]=A[i]*C[i]%mo;
DFT(A,-1,len);
fo(i,0,n-m) c[i]=A[n-m-i];
}
void poly_mod(ll *a,int n,ll *b,int m,ll *c)
{
int len=1;
for(;len<=n;len*=2);
poly_divide(a,n,b,m,c);
fo(i,n-m+1,len+len) c[i]=0;
fo(i,0,m-1) A[i]=b[i];
fo(i,m,len+len) A[i]=0;
DFT(A,1,len);DFT(c,1,len);
fo(i,0,len+len) A[i]=A[i]*c[i]%mo;
DFT(A,-1,len);
fo(i,0,m-2) c[i]=(a[i]-A[i]+mo)%mo;
}
void poly_sqrt(ll *a,ll *b,int deg)
{
if(deg==1)
{
b[0]=1; //默認常數爲1(不用二次剩餘)
return;
}
poly_sqrt(a,b,deg/2);
poly_inv(b,C,deg);
fo(i,0,deg-1) A[i]=a[i];
fo(i,deg,deg+deg) A[i]=0,C[i]=0;
DFT(A,1,deg);DFT(C,1,deg);
fo(i,0,deg+deg-1) A[i]=A[i]*C[i]%mo;
DFT(A,-1,deg);
ll ny2=mi(2,mo-2);
fo(i,0,deg-1) b[i]=(b[i]*ny2%mo+A[i]*ny2%mo)%mo;
}
int main()
{
int mx=0;
scanf("%d%d",&n,&m);
fo(i,1,n)
{
int x;scanf("%d",&x);
a[x]=mo-4;
mx+=x;
}
for(len=1;len<=m;len*=2);
a[0]++;
poly_sqrt(a,b,len);
b[0]++;
poly_inv(b,a,len);
fo(i,1,m) printf("%lld\n",2ll*a[i]%mo);
}