多项式模板集合
Posted yiqiatiya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式模板集合相关的知识,希望对你有一定的参考价值。
博主太菜惹。。。只放模板。。。
(FFT)
#include<bits/stdc++.h>
#define IL inline
#define LF double
using namespace std;
const int N=4e6+3;
const LF Pi=acos(-1.0);
int n,m,lim=1,cnt,r[N],tp;
struct comp{
LF x,y;
comp(LF xx=0,LF yy=0){x=xx,y=yy;}
IL comp operator+(const comp &a) const{return comp(x+a.x,y+a.y);}
IL comp operator-(const comp &a) const{return comp(x-a.x,y-a.y);}
IL comp operator*(const comp &a) const{return comp(x*a.x-y*a.y,x*a.y+y*a.x);}
}a[N],b[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
void FFT(comp *a,int op){
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
comp wn(cos(Pi/i),op*sin(Pi/i));
for(int j=0;j<lim;j+=i<<1){
comp w(1,0);
for(int k=0;k<i;++k,w=w*wn){
comp x=a[j+k],y=w*a[j+i+k];
a[j+k]=x+y,a[j+i+k]=x-y;
}
}
}
if(op==-1) for(int i=0;i<lim;++i) a[i].x=a[i].x/lim;
}
int main()
{
n=in()+1,m=in()+1;
while(lim<n+m) lim<<=1,++cnt;
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)<<cnt-1);
for(int i=0;i<n;++i) a[i].x=in();
for(int i=0;i<m;++i) b[i].x=in();
FFT(a,1),FFT(b,1);
for(int i=0;i<lim;++i) a[i]=a[i]*b[i];
FFT(a,-1);
for(int i=0;i<n+m-1;++i) printf("%d ",(int)(a[i].x/lim+0.5));
return 0;
}
(NTT)
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=4e6+3,p=998244353,G=3,Gi=332748118;
int n,m,a[N],b[N],r[N],lim=1,cnt,inv;
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL int ksm(int a,int b){
int c=1;
while(b){
if(b&1) c=1ll*c*a%p;
a=1ll*a*a%p,b>>=1;
}
return c;
}
void NTT(int *a,int op){
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
int wn=ksm(op?G:Gi,(p-1)/(i<<1));
for(int j=0;j<lim;j+=(i<<1)){
int w=1;
for(int k=0;k<i;++k,w=1ll*w*wn%p){
int x=a[j+k],y=1ll*w*a[j+i+k]%p;
a[j+k]=(x+y)%p,a[j+i+k]=(x-y+p)%p;
}
}
}
}
int main()
{
n=in()+1,m=in()+1;
for(int i=0;i<n;++i) a[i]=in();
for(int i=0;i<m;++i) b[i]=in();
while(lim<n+m) lim<<=1,++cnt;
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)<<cnt-1);
NTT(a,1),NTT(b,1);
for(int i=0;i<lim;++i) a[i]=1ll*a[i]*b[i]%p;
NTT(a,0),inv=ksm(lim,p-2);
for(int i=0;i<n+m-1;++i) printf("%lld ",1ll*a[i]*inv%p);
return 0;
}
多项式求逆
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define re register
using namespace std;
const int N=4e5+3,p=998244353,G=3,Gi=332748118;
int n,r[N],lim=1,op,cnt,bas;
LL a[N],b[N],c[N],d[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
re int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL LL ksm(re LL a,re LL b){
re LL c=1;
while(b){
if(b&1) c=c*a%p;
a=a*a%p,b>>=1;
}
return c;
}
IL LL mod(LL x){return x>=p?x-p:x;}
IL void calc(int lim){
for(re int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
IL void NTT(LL *a,int op){
for(re int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(re int i=1;i<lim;i<<=1){
LL wn=ksm(~op?G:Gi,(p-1)/(i<<1));
for(re int j=0;j<lim;j+=(i<<1)){
LL w=1;
for(re int k=0;k<i;++k,w=w*wn%p){
LL x=a[j+k],y=w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
LL inv=ksm(lim,p-2);
for(re int i=0;i<lim;++i) a[i]=a[i]*inv%p;
}
}
void solve(LL *a,LL *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);return;}
solve(a,b,n+1>>1);lim=1;
while(lim<(n<<1)) lim<<=1;calc(lim);
memcpy(c,a,8*n),memset(c+n,0,8*(lim-n));
NTT(c,1),NTT(b,1);
for(re int i=0;i<lim;++i) b[i]=mod(2+p-b[i]*c[i]%p)*b[i]%p;
NTT(b,-1),memset(b+n,0,8*(lim-n));
}
int main()
{
n=in();
for(re int i=0;i<n;++i) a[i]=in();
solve(a,b,n);
for(re int i=0;i<n;++i) printf("%lld ",b[i]);
return 0;
}
多项式除法
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define re register
using namespace std;
const int N=4e5+3,p=998244353,G=3,Gi=332748118;
int n,m,K,lim,r[N];
LL f[N],fr[N],g[N],gr[N],gv[N],q[N],R[N],a[N],b[N],c[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
re int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL LL ksm(re LL a,re LL b){
re LL c=1;
while(b){
if(b&1) c=c*a%p;
a=a*a%p,b>>=1;
}
return c;
}
IL LL mod(LL x){return x>=p?x-p:x;}
IL void calcrev(int lim){
for(re int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void init(){
n=in()+1,m=in()+1,K=n-m+1;
for(re int i=0;i<n;++i) f[i]=fr[i]=in();
for(re int i=0;i<m;++i) g[i]=gr[i]=in();
reverse(fr,fr+n),reverse(gr,gr+m);
}
IL void NTT(LL *a,int lim,int op){
for(re int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(re int i=1;i<lim;i<<=1){
re LL wn=ksm(~op?G:Gi,(p-1)/(i<<1));
for(re int j=0;j<lim;j+=(i<<1)){
re LL w=1;
for(re int k=0;k<i;++k,w=w*wn%p){
LL x=a[j+k],y=w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
LL inv=ksm(lim,p-2);
for(re int i=0;i<lim;++i) a[i]=a[i]*inv%p;
}
}
void get_inv(LL *a,LL *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);return;}
get_inv(a,b,n+1>>1);
lim=1;while(lim<(n<<1)) lim<<=1;calcrev(lim);
memcpy(c,a,8*n),memset(c+n,0,8*(lim-n));
NTT(c,lim,1),NTT(b,lim,1);
for(re int i=0;i<lim;++i) b[i]=mod(2-b[i]*c[i]%p+p)*b[i]%p;
NTT(b,lim,-1),memset(b+n,0,8*(lim-n));
}
IL void mul(LL *a,LL *b,int n,int m){
lim=1;while(lim<n+m) lim<<=1;calcrev(lim);
memcpy(c,b,8*m),memset(c+m,0,8*(lim-m)),memset(a+n,0,8*(lim-n));
NTT(a,lim,1),NTT(c,lim,1);
for(int i=0;i<lim;++i) a[i]=c[i]*a[i]%p;
NTT(a,lim,-1);
}
void divid(){
get_inv(gr,gv,K);
memcpy(q,fr,8*n);
mul(q,gv,n,K);
reverse(q,q+K);
mul(g,q,m,K);
for(re int i=0;i<m-1;++i) R[i]=mod(f[i]-g[i]+p);
for(re int i=0;i<K;++i) printf("%lld ",q[i]);printf("
");
for(re int i=0;i<m-1;++i) printf("%lld ",R[i]);
}
int main()
{
init();
divid();
return 0;
}
多项式对数函数
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=4e5+3,p=998244353,G=3,Gi=332748118;
int n,lim=1,r[N];
LL a[N],b[N],c[N],f[N],g[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL LL mod(LL x){return x>=p?x-p:x;}
IL LL ksm(LL a,LL b){
LL c=1;
while(b){
if(b&1) c=c*a%p;
a=a*a%p,b>>=1;
}
return c;
}
IL void calc(int lim){
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void NTT(LL *a,int lim,int op){
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
LL wn=ksm(~op?G:Gi,(p-1)/(i<<1));
for(int j=0;j<lim;j+=i<<1){
LL w=1;
for(int k=0;k<i;++k,w=w*wn%p){
LL x=a[j+k],y=w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
LL inv=ksm(lim,p-2);
for(int i=0;i<lim;++i) a[i]=a[i]*inv%p;
}
}
void get_inv(LL *a,LL *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);return;}
get_inv(a,b,n+1>>1);
lim=1;while(lim<2*n) lim<<=1;calc(lim);
memcpy(c,a,8*n),memset(c+n,0,8*(lim-n));
NTT(c,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;++i) b[i]=mod(2-c[i]*b[i]%p+p)*b[i]%p;
NTT(b,lim,-1),memset(b+n,0,8*(lim-n));
}
IL void get_dao(LL *a,LL *b,int n){for(int i=0;i<n-1;++i) b[i]=(i+1)*a[i+1]%p;b[n-1]=0;}
IL void jifen(LL *a,LL *b,int n){for(int i=1;i<n;++i) b[i]=a[i-1]*ksm(i,p-2)%p;b[0]=0;}
IL void get_ln(LL *f,LL *g,int n){
get_dao(f,a,n),get_inv(f,b,n);
lim=1;while(lim<2*n) lim<<=1;calc(lim);
NTT(a,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;++i) a[i]=a[i]*b[i]%p;
NTT(a,lim,-1),jifen(a,g,n);
}
int main()
{
n=in();
for(int i=0;i<n;++i) f[i]=in();
get_ln(f,g,n);
for(int i=0;i<n;++i) printf("%lld ",g[i]);
return 0;
}
以上是关于多项式模板集合的主要内容,如果未能解决你的问题,请参考以下文章