【模板】多项式
FFT
FFT模板(正常)
//Author:RingweEH
//P3803 【模板】多项式乘法(FFT)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return (a<b) ? a : b; }
int max( int a,int b ) { return (a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
int read()
{
int x=0; char ch=getchar();
while ( ch>'9' || ch<'0' ) ch=getchar();
while ( ch<='9' && ch>='0' ) x=x*10+ch-48,ch=getchar();
return x;
}
const int N=2100000;
const db PI=acos(-1.0)*2;
int n,m,rev[N];
struct Complex
{
db x,y;
Complex( db _x=0,db _y=0 ) : x(_x),y(_y) {}
}F[N],G[N];
Complex operator + ( Complex t1,Complex t2 ) { return Complex(t1.x+t2.x,t1.y+t2.y); }
Complex operator - ( Complex t1,Complex t2 ) { return Complex(t1.x-t2.x,t1.y-t2.y); }
Complex operator * ( Complex t1,Complex t2 ) { return Complex(t1.x*t2.x-t1.y*t2.y,t1.x*t2.y+t1.y*t2.x); }
void FFT( int lim,Complex *f,bool fl )
{
int i,k,len,l;
for ( i=0; i<lim; i++ ) if ( i<rev[i] ) swap( f[i],f[rev[i]] );
for ( k=2,len; k<=lim; k<<=1 )
{
len=k>>1; Complex w(cos(PI/k),sin(PI/k));
if ( !fl ) w.y*=-1;
for ( i=0; i<lim; i+=k )
{
Complex buf(1,0);
for ( l=i; l<i+len; l++ )
{
Complex tmp=buf*f[len+l];
f[len+l]=f[l]-tmp; f[l]=f[l]+tmp;
buf=buf*w;
}
}
}
}
int main()
{
n=read(); m=read(); int i;
for ( i=0; i<=n; i++ ) F[i].x=read();
for ( i=0; i<=m; i++ ) G[i].x=read();
int lim=1; for ( ; lim<=(n+m); lim<<=1 );
for ( i=0; i<lim; i++ ) rev[i]=(rev[i>>1]>>1)|((i&1) ? lim>>1 : 0);
FFT( lim,F,1 ); FFT( lim,G,1 ); //DFT
for ( i=0; i<lim; i++ ) F[i]=F[i]*G[i];
FFT( lim,F,0 ); //IDFT
for ( i=0; i<=n+m; i++ ) printf( "%d ",(int)(F[i].x/lim+0.49) );
return 0;
}
FFT模板(三变二)
//Author:RingweEH
//P3803 【模板】多项式乘法(FFT)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return (a<b) ? a : b; }
int max( int a,int b ) { return (a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
char buf[1<<20],*p1=buf,*p2=buf;
int read()
{
int x=0; char ch=getchar();
while ( ch>'9' || ch<'0' ) ch=getchar();
while ( ch<='9' && ch>='0' ) x=x*10+ch-48,ch=getchar();
return x;
}
void write( int x ) { if(x<0) putchar(45); if ( x>9 ) write(x/10); putchar(x%10+48); }
const int N=2100000;
const db PI=acos(-1.0)*2;
int n,m,rev[N];
struct Complex
{
db x,y;
Complex( db _x=0,db _y=0 ) : x(_x),y(_y) {}
}F[N];//,G[N];
Complex operator + ( Complex t1,Complex t2 ) { return Complex(t1.x+t2.x,t1.y+t2.y); }
Complex operator - ( Complex t1,Complex t2 ) { return Complex(t1.x-t2.x,t1.y-t2.y); }
Complex operator * ( Complex t1,Complex t2 ) { return Complex(t1.x*t2.x-t1.y*t2.y,t1.x*t2.y+t1.y*t2.x); }
void FFT( Complex *f,bool fl )
{
int i,k,len,l;
for ( i=0; i<n; i++ )
if ( i<rev[i] ) swap( f[i],f[rev[i]] );
for ( k=2,len; k<=n; k<<=1 )
{
len=k>>1; Complex w(cos(PI/k),sin(PI/k));
if ( !fl ) w.y*=-1;
for ( i=0; i<n; i+=k )
{
Complex buf(1,0);
for ( l=i; l<i+len; l++ )
{
Complex tmp=buf*f[len+l];
f[len+l]=f[l]-tmp; f[l]=f[l]+tmp;
buf=buf*w;
}
}
}
}
int main()
{
n=read(); m=read(); int i;
for ( i=0; i<=n; i++ ) F[i].x=read();
for ( i=0; i<=m; i++ ) F[i].y=read();
for ( m+=n,n=1; n<=m; n<<=1 );
for ( i=0; i<n; i++ ) rev[i]=(rev[i>>1]>>1)|((i&1) ? n>>1 : 0);
FFT( F,1 ); //FFT( G,1 ); //DFT
for ( i=0; i<n; i++ ) F[i]=F[i]*F[i];
FFT( F,0 ); //IDFT
for ( i=0; i<=m; i++ )
write((int)(F[i].y/n/2+0.49)),putchar(32);
//printf( "%d ",(int)(F[i].y/n/2+0.49) ); //printf( "%d ",(int)(F[i].x/n+0.49) );
return 0;
}
NTT
NTT
//Author:RingweEH
//P3803 【模板】多项式乘法(FFT)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return (a<b) ? a : b; }
int max( int a,int b ) { return (a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
char buf[1<<20],*p1=buf,*p2=buf;
int read()
{
int x=0; char ch=getchar();
while ( ch>'9' || ch<'0' ) ch=getchar();
while ( ch<='9' && ch>='0' ) x=x*10+ch-48,ch=getchar();
return x;
}
void write( int x ) { if(x<0) putchar(45); if ( x>9 ) write(x/10); putchar(x%10+48); }
void swap( ll &a,ll &b ) { a^=b; b^=a; a^=b; }
const int N=2100000;
const ll Mod=998244353,G=3,InvG=332748118;
int n,m,rev[N];
ll f[N],g[N],Invn;
ll power( ll a,ll b=Mod-2 )
{
ll res=1;
for ( ; b; b>>=1,a=a*a%Mod )
if ( b&1 ) res=res*a%Mod;
return res;
}
void NTT( ll *f,bool fl )
{
int i,k,len,l;
for ( i=0; i<n; i++ )
if ( i<rev[i] ) swap( f[i],f[rev[i]] );
for ( k=2; k<=n; k<<=1 )
{
len=k>>1; ll nwG=power( fl ? G : InvG,(Mod-1)/k );
for ( i=0; i<n; i+=k )
{
ll buf=1;
for ( l=i; l<i+len; l++ )
{
ll tmp=buf*f[len+l]%Mod;
f[len+l]=f[l]-tmp;
if ( f[len+l]<0 ) f[len+l]+=Mod;
f[l]=f[l]+tmp;
if ( f[l]>=Mod ) f[l]-=Mod;
buf=buf*nwG%Mod;
}
}
}
}
int main()
{
n=read(); m=read(); int i;
for ( i=0; i<=n; i++ ) f[i]=read();
for ( i=0; i<=m; i++ ) g[i]=read();
for ( m+=n,n=1; n<=m; n<<=1 );
for ( i=0; i<n; i++ ) rev[i]=(rev[i>>1]>>1)|((i&1) ? n>>1 : 0);
NTT( f,1 ); NTT( g,1 );
for ( i=0; i<n; i++ ) f[i]=f[i]*g[i]%Mod;
NTT( f,0 ); Invn=power(n);
for ( i=0; i<=m; i++ )
write((int)(f[i]*Invn%Mod)),putchar(32);
return 0;
}
分治FFT
//Author: RingweEH
//P4721 【模板】分治FFT
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return a<b ? a : b; }
int max( int a,int b ) { return a>b ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
void swap( int &a,int &b ) { a^=b; b^=a; a^=b; }
inline int read()
{
int x=0; char ch=getchar();
while ( ch>'9' || ch<'0' ) ch=getchar();
while ( ch<='9' && ch>='0' ) x=x*10+ch-48,ch=getchar();
return x;
}
#define Mod 998244353
const int N=1e5+10,M=4e5+10;
namespace Math
{
int inv[N];//,fac[N],infac[N];
int power( int a,int b ) { int res=1; for (;b;b>>=1,a=1ll*a*a%Mod) if (b&1) res=1ll*a*res%Mod; return res; }
inline void bmod( int &x ) { x-=Mod; x+=x>>31&Mod; }
};
using Math :: power;
using Math :: bmod;
namespace Poly
{
#define Clear(a,n) memset(a,0,sizeof(int)*n)
#define Copy(a,b,n) memcpy(a,b,sizeof(int)*n)
#define Rev(a,b) reverse(a,b)
int rev[M],rt[M],lim,lg,lasn; //反转数组,原根,上界的值和log
void Poly_Init( int n )
{
if ( n==lasn ) return; lasn=n; int i,j,w;
for ( lg=0,lim=1; lim<n; lg++,lim<<=1 );
for ( i=0; i<lim; i++ ) rev[i]=(rev[i>>1]>>1) | ((i&1)<<(lg-1));
for ( i=1; i<lim; i<<=1 )
{
w=power(3,(Mod-1)/(i<<1)); rt[i]=1;
for ( j=1; j<i; j++ ) rt[i+j]=1ll*rt[i+j-1]*w%Mod;
}
}
void NTT( int *f,int opt )
{
int i,j,k,invn,len,t1,t2;
for ( i=0; i<lim; i++ ) if ( i>rev[i] ) swap( f[i],f[rev[i]] );
for ( i=1; i<lim; i<<=1 )
for ( j=0; j<lim; j+=i<<1 )
for ( k=0; k<i; k++ )
{
t1=f[j+k]; t2=1ll*rt[i+k]*f[i+j+k]%Mod;
bmod(f[j+k]=t1+t2); bmod(f[i+j+k]=t1+Mod-t2);
}
if ( opt ) return; invn=power(lim,Mod-2);
for ( i=0; i<lim; i++ ) f[i]=1ll*f[i]*invn%Mod;
}
void Poly_InitPart( int n )
{
if ( n==lasn ) return; lasn=n; int i,j,w;
for ( lg=0,lim=1; lim<n; lg++,lim<<=1 );
for ( i=0; i<lim; i++ ) rev[i]=(rev[i>>1]>>1) | ((i&1)<<(lg-1));
}
};
using Poly :: NTT;
using Poly :: Poly_Init;
using Poly :: Poly_InitPart;
int n,F[M],G[M],ans[M],H[M];
void CDQ_NTT( int l,int r )
{
if ( l+1>=r ) return;
int mid=(l+r)>>1,len=r-l,i; CDQ_NTT(l,mid);
Poly_InitPart(len);
for ( i=0; i<len; i++ ) G[i]=H[i];
for ( i=l; i<mid; i++ ) F[i-l]=ans[i];
for ( i=mid; i<r; i++ ) F[i-l]=0;
NTT( F,1 ); NTT( G,1 );
for ( int i=0; i<len; i++ ) F[i]=1ll*F[i]*G[i]%Mod;
reverse(F+1,F+len); NTT( F,0 );
for ( i=mid; i<r; i++ ) bmod(ans[i]+=F[i-l]);
CDQ_NTT(mid,r);
}
int main()
{
n=read();
for ( int i=1; i<n; i++ ) H[i]=read();
Poly_Init(n); ans[0]=1; CDQ_NTT(0,Poly::lim);
for ( int i=0; i<n; i++ ) printf( "%d ",ans[i] );
return 0;
}
任意模数NTT
//Author: RingweEH
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return a<b ? a : b; }
int max( int a,int b ) { return a>b ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
int read()
{
int x=0,w=1; char ch=getchar();
while ( ch>'9' || ch<'0' ) { if ( ch=='-' ) w=-1; ch=getchar(); }
while ( ch<='9' && ch>='0' ) x=x*10+ch-'0',ch=getchar();
return x*w;
}
inline int power( int a,int b,int Mod ) { int res=1; for (;b;b>>=1,a=1ll*a*a%Mod) if (b&1) res=1ll*a*res%Mod; return res; }
inline int Get_Inv( int x,int Mod ) { return power(x,Mod-2,Mod); }
inline int pmod( int x,int Mod ) { return x+=x>>31&Mod; }
const int Mod1=998244353,Mod2=1004535809,Mod3=469762049,Gn=3,M=4e5+10;
const ll Mod12=1ll*Mod1*Mod2;
const int Inv1=Get_Inv(Mod1,Mod2),Inv2=Get_Inv(Mod12%Mod3,Mod3);
int Mod;
struct ModInt
{
int x1,x2,x3;
ModInt( int _x1=0,int _x2=0,int _x3=0 ) : x1(_x1),x2(_x2),x3(_x3) {}
ModInt operator + ( ModInt t )
{ return ModInt( pmod(x1+t.x1-Mod1,Mod1),pmod(x2+t.x2-Mod2,Mod2),pmod(x3+t.x3-Mod3,Mod3) ); }
ModInt operator - ( ModInt t )
{ return ModInt( pmod(x1-t.x1,Mod1),pmod(x2-t.x2,Mod2),pmod(x3-t.x3,Mod3) ); }
ModInt operator * ( ModInt t )
{ return ModInt( 1ll*x1*t.x1%Mod1,1ll*x2*t.x2%Mod2,1ll*x3*t.x3%Mod3 ); }
int Merge()
{
ll t1=1ll*(x2-x1+Mod2)%Mod2*Inv1%Mod2*Mod1+x1;
ll t2=(x3-t1%Mod3+Mod3)%Mod3; t2=t2*Inv2%Mod3*(Mod12%Mod)%Mod; t2=t2+t1%Mod; t2%=Mod;
return t2;
}
}rt[M];
int lim,Lg,rev[M];
void Poly_Init( int n )
{
for (lim=1,Lg=0 ; lim<=n; lim<<=1,Lg++ );
for ( int i=0; i<lim; i++ ) rev[i]=(rev[i>>1]>>1) | ((i&1)<<(Lg-1));
for ( int i=1; i<lim; i<<=1 )
{
ModInt nw(power(Gn,(Mod1-1)/(i<<1),Mod1),power(Gn,(Mod2-1)/(i<<1),Mod2),
power(Gn,(Mod3-1)/(i<<1),Mod3));
rt[i]=ModInt(1,1,1);
for ( int j=1; j<i; j++ ) rt[i+j]=rt[i+j-1]*nw;
}
}
void NTT( ModInt *f,int opt )
{
int i,j,k,len; ModInt t1,t2;
for ( i=0; i<lim; i++ ) if ( i>rev[i] ) swap( f[i],f[rev[i]] );
for ( i=1; i<lim; i<<=1 )
for ( j=0; j<lim; j+=i<<1 )
for ( k=0; k<i; k++ )
{
t1=f[j+k]; t2=rt[i+k]*f[i+j+k];
f[j+k]=t1+t2; f[i+j+k]=t1-t2;
} if ( opt ) return;
ModInt invn=ModInt(Get_Inv(lim,Mod1),Get_Inv(lim,Mod2),Get_Inv(lim,Mod3));
for ( i=0; i<lim; i++ ) f[i]=f[i]*invn;
}
int n,m;
ModInt F[M],G[M];
int main()
{
n=read(); m=read(); Mod=read(); n++; m++;
for ( int i=0,x; i<n; i++ ) x=read()%Mod,F[i]=ModInt(x,x,x);
for ( int i=0,x; i<m; i++ ) x=read()%Mod,G[i]=ModInt(x,x,x);
Poly_Init( n+m ); NTT( F,1 ); NTT( G,1 );
for ( int i=0; i<lim; i++ ) F[i]=F[i]*G[i];
reverse(F+1,F+lim); NTT( F,0 );
for ( int i=0; i<n+m-1; i++ )
printf( "%d ",F[i].Merge() );
return 0;
}
FWT
FWT模板
//Author: RingweEH
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return a<b ? a : b; }
int max( int a,int b ) { return a>b ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
int read()
{
int x=0,w=1; char ch=getchar();
while ( ch>'9' || ch<'0' ) { if ( ch=='-' ) w=-1; ch=getchar(); }
while ( ch<='9' && ch>='0' ) x=x*10+ch-'0',ch=getchar();
return x*w;
}
const int N=5e5+10,Mod=998244353,Inv2=499122177;
inline int bmod( int x ) { return x+=x>>31&Mod; }
int lim,F[N],G[N],n,ans[N];
void FWT_Or( int *f,int opt )
{
int i,j,k,len;
for ( i=2; i<lim; i<<=1 )
for ( len=(i>>1),j=0; j<lim; j+=i )
for ( k=j; k<j+len; k++ )
(f[k+len]+=bmod(1ll*f[k]*opt%Mod))%=Mod;
}
void FWT_And( int *f,int opt )
{
int i,j,k,len;
for ( i=2; i<lim; i<<=1 )
for ( len=(i>>1),j=0; j<lim; j+=i )
for ( k=j; k<j+len; k++ )
(f[k]+=bmod(1ll*f[k+len]*opt))%=Mod;
}
void FWT_Xor( int *f,int opt )
{
int i,j,k,len;
for ( i=2; i<lim; i<<=1 )
for ( len=i>>1,j=0; j<lim; j+=i )
for ( k=j; k<j+len; k++ )
{
int t1=f[k],t2=f[k+len];
f[k]=(t1+t2)%Mod; f[k+len]=(t1+Mod-t2)%Mod;
if ( opt==-1 ) f[k]=1ll*f[k]*Inv2%Mod,f[k+len]=1ll*f[k+len]*Inv2%Mod;
}
}
void Poly_Mul( int n,int *f,int *g,int *res,int opt )
{
for ( lim=1; lim<=n; lim<<=1 );
static int tf[N],tg[N];
memcpy( tf,f,sizeof(int)*n ); memcpy( tg,g,sizeof(int)*n );
memset( tf+n,0,sizeof(int)*(lim-n) ); memset( tg+n,0,sizeof(int)*(lim-n) );
if ( opt==0 )
{
FWT_Or( tf,1 ); FWT_Or( tg,1 );
for ( int i=0; i<lim; i++ ) tf[i]=1ll*tf[i]*tg[i]%Mod;
FWT_Or( tf,-1 );
memcpy( res,tf,sizeof(int)*n ); memset( res+n,0,sizeof(int)*(lim-n) );
return;
}
else if ( opt==1 )
{
FWT_And( tf,1 ); FWT_And( tg,1 );
for ( int i=0; i<lim; i++ ) tf[i]=1ll*tf[i]*tg[i]%Mod;
FWT_And( tf,-1 );
memcpy( res,tf,sizeof(int)*n ); memset( res+n,0,sizeof(int)*(lim-n) );
return;
}
else if ( opt==2 )
{
FWT_Xor( tf,1 ); FWT_Xor( tg,1 );
for ( int i=0; i<lim; i++ ) tf[i]=1ll*tf[i]*tg[i]%Mod;
FWT_Xor( tf,-1 );
memcpy( res,tf,sizeof(int)*n ); memset( res+n,0,sizeof(int)*(lim-n) );
return;
}
}
int main()
{
n=read(); n=1<<n;
for ( int i=0; i<n; i++ ) F[i]=read();
for ( int i=0; i<n; i++ ) G[i]=read();
Poly_Mul( n,F,G,ans,0 );
for ( int i=0; i<n; i++ ) printf( "%d ",ans[i] ); puts("");
Poly_Mul( n,F,G,ans,1 );
for ( int i=0; i<n; i++ ) printf( "%d ",ans[i] ); puts("");
Poly_Mul( n,F,G,ans,2 );
for ( int i=0; i<n; i++ ) printf( "%d ",ans[i] ); puts("");
return 0;
}
多项式全家桶
多项式全家桶
//Author: RingweEH
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return a<b ? a : b; }
int max( int a,int b ) { return a>b ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
void swap( int &a,int &b ) { a^=b; b^=a; a^=b; }
inline int read()
{
int x=0; char ch=getchar();
while ( ch>'9' || ch<'0' ) ch=getchar();
while ( ch<='9' && ch>='0' ) x=x*10+ch-48,ch=getchar();
return x;
}
#define Mod 998244353
inline int readMod()
{
ll x=0; char ch=getchar();
while ( ch>'9' || ch<'0' ) ch=getchar();
while ( ch<='9' && ch>='0' ) x=(x*10ll+ch-48)%Mod,ch=getchar();
return (int)x;
}
const int N=1e5+10,M=4e5+10;
namespace Math
{
int inv[N];//,fac[N],infac[N];
int power( int a,int b ) { int res=1; for (;b;b>>=1,a=1ll*a*a%Mod) if (b&1) res=1ll*a*res%Mod; return res; }
inline void bmod( int &x ) { x-=Mod; x+=x>>31&Mod; }
void Init( int n=N-1 )
{
inv[1]=1; for ( int i=2; i<=n; i++ ) inv[i]=1ll*inv[Mod%i]*(Mod-Mod/i)%Mod;
//fac[0]=1; for ( int i=1; i<=n; i++ ) fac[i]=1ll*i*fac[i-1]%Mod;
//infac[n]=power(fac[n],Mod-2); for ( int i=n-1; i>=0; i-- ) infac[i]=1ll*(i+1)*infac[i+1]%Mod;
}
};
using Math :: power;
using Math :: bmod;
namespace Poly
{
#define Clear(a,n) memset(a,0,sizeof(int)*(n))
#define Copy(a,b,n) memcpy(a,b,sizeof(int)*(n))
#define Rev(a,b) reverse(a,b)
int rev[M],rt[M],lim,lg,lasn; //反转数组,原根,上界的值和log
void Poly_Init( int n )
{
if ( n==lasn ) return; lasn=n; int i,j,w;
for ( lg=0,lim=1; lim<=n; lg++,lim<<=1 );
for ( i=0; i<lim; i++ ) rev[i]=(rev[i>>1]>>1) | ((i&1)<<(lg-1));
for ( i=1; i<lim; i<<=1 )
{
w=power(3,(Mod-1)/(i<<1)); rt[i]=1;
for ( j=1; j<i; j++ ) rt[i+j]=1ll*rt[i+j-1]*w%Mod;
}
}
void NTT( int *f,int opt )
{
int i,j,k,invn,len,t1,t2;
for ( i=0; i<lim; i++ ) if ( i>rev[i] ) swap( f[i],f[rev[i]] );
for ( i=1; i<lim; i<<=1 )
for ( j=0; j<lim; j+=i<<1 )
for ( k=0; k<i; k++ )
{
t1=f[j+k]; t2=1ll*rt[i+k]*f[i+j+k]%Mod;
bmod(f[j+k]=t1+t2); bmod(f[i+j+k]=t1+Mod-t2);
}
if ( opt ) return; invn=power(lim,Mod-2);
for ( i=0; i<lim; i++ ) f[i]=1ll*f[i]*invn%Mod;
}
void Poly_Mul( int n,int m,int *f,int *g,int *res )
{
Poly_Init(n+m); static int tf[M],tg[M];
Copy(tf,f,n); Clear(tf+n,lim-n); NTT(tf,1);
Copy(tg,g,m); Clear(tg+m,lim-m); NTT(tg,1);
for ( int i=0; i<lim; i++ ) tf[i]=1ll*tf[i]*tg[i]%Mod;
Rev(tf+1,tf+lim); NTT(tf,0); Copy(res,tf,n+m-1);
}
void Poly_Inv( int n,int *f,int *g )
{ //G(x)\equiv 2H(x)-H(x)^2F(x)(\bmod x^n)
static int tf[M];
if ( n==1 ) { g[0]=power(f[0],Mod-2); return; }
Poly_Inv((n+1)>>1,f,g); Poly_Init(n<<1);
Copy(tf,f,n); Clear(tf+n,lim-n); Clear(g+n,lim-n); NTT(tf,1); NTT(g,1);
for ( int i=0; i<lim; i++ ) g[i]=1ll*g[i]*(2+Mod-1ll*g[i]*tf[i]%Mod)%Mod;
Rev(g+1,g+lim); NTT(g,0); Clear(g+n,lim-n);
}
void Itg( int n,int *f,int *g ) //Intergral
{
for ( int i=1; i<=n; i++ ) g[i]=1ll*f[i-1]*Math::inv[i]%Mod; g[0]=0;
}
void Drv( int n,int *f,int *g ) //Derivative
{
for ( int i=0; i<n-1; i++ ) g[i]=1ll*(i+1)*f[i+1]%Mod; g[n-1]=0;
}
void Poly_ln( int n,int *f,int *g )
{
static int tf[M],tg[M];
Drv(n,f,tf); Clear(tg,n); Poly_Inv(n,f,tg);
Poly_Mul(n,n,tf,tg,tf); Itg(n,tf,g);
}
void Poly_Exp( int n,int *f,int *g )
{ //G(x)=H(x)(1-\ln(H(x))+A(x))
if ( n==1 ) { g[0]=1; return; } static int tf[M];
Poly_Exp( (n+1)>>1,f,g ); Clear(tf,n); Poly_ln(n,g,tf); tf[0]--;
for ( int i=0; i<n; i++ ) bmod( tf[i]=f[i]+Mod-tf[i] );
Poly_Mul(n,n,g,tf,g); Clear(g+n,lim-n);
}
void Poly_Sqrt( int powe,int *f,int *g )
{//F(x)=\dfrac{H(x)^2+A(x)}{2H(x)}
if ( powe==1 ) { g[0]=1; return; }
static int tf[M]; Poly_Sqrt((powe+1)>>1,f,g);
Clear(tf,powe); Poly_Inv(powe,g,tf); Poly_Mul(powe,powe,tf,f,tf);
int inv2=power(2,Mod-2); for ( int i=0; i<powe; i++ ) g[i]=1ll*(g[i]+tf[i])*inv2%Mod;
}
void Poly_Power( int n,int k,int *f,int *g )
{
static int tf[M]; Clear(tf,n); Poly_ln(n,f,tf);
for ( int i=0; i<n; i++ ) tf[i]=1ll*tf[i]*k%Mod;
Poly_Exp(n,tf,g);
}
void Poly_DivMod( int n,int m,int *f,int *g,int *q,int *r )
{ //F^R(x)\equiv G^R(x)Q^R(x)\pmod {x^{n-m+1}}
static int tf[M],tg[M],nw[M];
Copy(tf,f,n); Copy(tg,g,m); Rev(tf,tf+n); Rev(tg,tg+m);
for ( int i=n-m+1; i<(n<<1); i++ ) tg[i]=0;
Poly_Inv(n-m+1,tg,nw); Poly_Mul(n,n-m+1,tf,nw,q);
for ( int i=n-m+1; i<(n<<1); i++ ) q[i]=0;
Rev(q,q+n-m+1); Poly_Mul(n-m+1,m,q,g,r);
}
};
int main()
{
//freopen( "exam.in","r",stdin );
return 0;
}
多项式多点求值
//-------------------多点求值---------------------
#define lc (pos<<1)
#define rc (pos<<1|1)
int GMod[N<<6],*arr=GMod,*Evg[M];
void Eval_Mul( int n,int m,int *f,int *g,int *res ) //Evaluation
{
static int tf[M],tg[M]; Poly_Init(n);
Copy(tf,f,n); Clear(tf+n,lim-n); NTT( tf,1 );
Copy(tg,g,m); Clear(tg+m,lim-m); NTT( tg,1 );
for ( int i=0; i<lim; i++ ) tf[i]=1ll*tf[i]*tg[i]%Mod;
reverse( tf+1,tf+lim ); NTT( tf,0 ); Copy( res,tf+m-1,n-m+1 );
}
void Eval_Pre( int l,int r,int pos,int *f )
{
Evg[pos]=arr; arr+=r-l+1;
if ( r-l==1 ) { Evg[pos][0]=Mod-f[l],Evg[pos][1]=1; return; }
int mid=(l+r)>>1;
Eval_Pre( l,mid,lc,f ); Eval_Pre( mid,r,rc,f );
Poly_Mul( mid-l+1,r-mid+1,Evg[lc],Evg[rc],Evg[pos] );
}
void Eval_Sol( int l,int r,int pos,int *f,int *g )
{
if ( r-l==1 ) { g[l]=f[0]; return; }
int mid=(l+r)>>1,*fl,*fr;
fl=arr; arr+=mid-l; fr=arr; arr+=r-mid;
Eval_Mul( r-l,r-mid+1,f,Evg[rc],fl );
Eval_Mul( r-l,mid-l+1,f,Evg[lc],fr );
Eval_Sol( l,mid,lc,fl,g ); Eval_Sol( mid,r,rc,fr,g );
}
void Poly_Eval( int n,int m,int *a,int *f,int *g )
{
static int t[M]; n=max( n,m );
Eval_Pre( 0,n,1,a ); reverse( Evg[1],Evg[1]+n+1 );
Poly_Inv( n,Evg[1],t ); reverse( t,t+n );
Poly_Mul( n,n,t,f,t ); Copy( t,t+n,n );
Eval_Sol( 0,n,1,t,g );
for ( int i=0; i<m; i++ ) bmod( g[i]=1ll*g[i]*a[i]%Mod+f[0] );
for ( int i=m; i<n; i++ ) g[i]=0;
}
多项式快速插值
//Author: RingweEH
#define Mod 998244353
const int N=1e5+10,M=4e5+10;
int power( int a,int b ) { int res=1; for (;b;b>>=1,a=1ll*a*a%Mod) if (b&1) res=1ll*a*res%Mod; return res; }
inline int bmod( int x ) { x-=Mod; x+=x>>31&Mod; return x; }
namespace Poly
{
void Poly_Mod( int n,int m,int *f,int *g,int *r )
{ //F^R(x)\equiv G^R(x)Q^R(x)\pmod {x^{n-m+1}}
static int tf[M],tg[M],nw[M],q[M]; Poly_Init(n+m);
Copy(tf,f,n); Copy(tg,g,m); Rev(tf,tf+n); Rev(tg,tg+m);
for ( int i=n-m+1; i<(n<<1); i++ ) tg[i]=0;
Poly_Inv(n-m+1,tg,nw); Poly_Mul(n,n-m+1,tf,nw,q);
for ( int i=n-m+1; i<(n<<1); i++ ) q[i]=0;
Rev(q,q+n-m+1); Copy(nw,g,m); Poly_Mul(n-m+1,m,q,nw,r);
for ( int i=0; i<m-1; i++ ) r[i]=bmod(f[i]-r[i]+Mod);
}
};
using namespace Poly;
#define lc pos<<1
#define rc pos<<1|1
int x[N],y[N],*F[M],n,H[M],v[M];
int *Evg[M],len[M];
void Prework( int l,int r,int pos )
{
if ( l==r ) { len[pos]=2; Evg[pos]=new int[2]; Evg[pos][0]=Mod-x[l]; Evg[pos][1]=1; return; }
static int t[M]; int mid=(l+r)>>1;
Prework(l,mid,lc); Prework(mid+1,r,rc);
len[pos]=len[lc]+len[rc]-1; Evg[pos]=new int[len[pos]];
Poly_Mul( len[lc],len[rc],Evg[lc],Evg[rc],t );
for ( int i=0; i<len[pos]; i++ ) Evg[pos][i]=t[i];
}
void Solve( int l,int r,int pos,int *f )
{
if ( l==r ) { v[l]=f[0]; return; }
int t[len[pos]<<1]; int mid=(l+r)>>1; memset(t,0,sizeof(t));
Poly_Mod( len[pos]-1,len[lc],f,Evg[lc],t );
Solve( l,mid,lc,t );
Poly_Mod( len[pos]-1,len[rc],f,Evg[rc],t );
Solve( mid+1,r,rc,t );
}
void Merge( int l,int r,int pos )
{
if ( l==r ) { F[pos]=new int[2]; F[pos][0]=v[l]; F[pos][1]=0; return; }
static int fl[M],fr[M]; int mid=(l+r)>>1;
Merge( l,mid,lc ); Merge( mid+1,r,rc );
Poly_Mul( len[lc],len[rc],F[lc],Evg[rc],fl );
Poly_Mul( len[rc],len[lc],F[rc],Evg[lc],fr );
F[pos]=new int[len[pos]];
for ( int i=0; i<len[pos]; i++ ) F[pos][i]=bmod(fl[i]+fr[i]);
}
signed main()
{
n=read();
for ( int i=1; i<=n; i++ ) x[i]=read(),y[i]=read();
Prework(1,n,1);
Drv( len[1],Evg[1],H );
Solve( 1,n,1,H );
for ( int i=1; i<=n; i++ ) v[i]=1ll*power(v[i],Mod-2)*y[i]%Mod;
Merge( 1,n,1 );
for ( int i=0; i<n; i++ ) printf( "%d ",F[1][i] );
return 0;
}
多项式三角函数
const int TriI=86583718,Inv2=power(2,Mod-2),InvI=power(TriI,Mod-2);
void Poly_SinCos( int n,int *f,int *g,int opt ) //0:sin,1:cos
{
Poly_Init(n); static int tf[M];
Copy(tf,f,n); Clear(tf+n,lim-n);
for ( int i=0; i<n; i++ ) tf[i]=1ll*tf[i]*TriI%Mod;
Poly_Exp( n,tf,g ); Clear(tf,lim); Poly_Inv( n,g,tf ); //g:exp(if(x)),tf:exp(-if(x))
if ( !opt )
{
for ( int i=0; i<n; i++ ) bmod(g[i]+=Mod-tf[i]);
int cons=1ll*Inv2*InvI%Mod;
for ( int i=0; i<n; i++ ) g[i]=1ll*g[i]*cons%Mod;
Clear(g+n,lim-n);
}
else
{
for ( int i=0; i<n; i++ ) bmod(g[i]+=tf[i]);
for ( int i=0; i<n; i++ ) g[i]=1ll*g[i]*Inv2%Mod;
Clear(g+n,lim-n);
}
}
大地也该是从一片类似的光明中冒出来的。