[多项式] 多项式跑飞快/石室中学秘传模板

终于把多项式板子打完啦!

最后补充一点三角函数的芝士

cos ⁡ F \cos F cosF sin ⁡ F \sin F sinF
想到伟大的欧拉公式!
e θ i = cos ⁡ θ + i sin ⁡ θ e^{\theta i}=\cos \theta +i\sin \theta eθi=cosθ+isinθ
θ \theta θ看成多项式一样的

推柿子
得到:
cos ⁡ F = e F i + e − F i 2 sin ⁡ F = e F i − e − F i 2 i \cos F=\frac{e^{Fi}+e^{-Fi}}{2}\\ \sin F=\frac{e^{Fi}-e^{-Fi}}{2i} cosF=2eFi+eFisinF=2ieFieFi

有点难搞的就只剩虚单位 i i i了!
虚单位。。。虚单位根?
妙啊!
联想丑陋的FFT
i i i w 4 w_4 w4,有 i 4 = 1 i^4=1 i4=1
模意义下呢?
x 4 ≡ 1 x^4\equiv 1 x41
x = g m o d − 1 4 x=g^{\frac{mod-1}{4}} x=g4mod1
完美

下面看下石室中学秘传板子

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> poly;
#define cs const
#define pb push_back
#define in Read()
int in{
	int i=0,f=1;char ch=0;
	while(!isdigit(ch)&&ch!='-') ch=getchar();
	if(ch=='-') ch=getchar(),f=-1;
	while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
	return i*f;
}

cs int mod=998244353,N=5e6+5;
int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
int dec(int a,int b){return a<b?a-b+mod:a-b;}
int mul(int a,int b){return 1ll*a*b%mod;}
int qpw(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=mul(res,a);
		a=mul(a,a);
		b>>=1;
	}
	return res;
}
cs int inv2=mod+1>>1;

void print(cs poly &f){
	for(int i=0;i<f.size();++i)
		printf("%d ",f[i]);
	return;
}

int rev[N],inv[N],fac[N],ifac[N],lim;
void init(int deg){
	lim=1;
	while(lim<deg) lim<<=1;
	for(int i=0;i<lim;++i)
		rev[i]=(rev[i>>1]>>1)|((i&1)?lim>>1:0);
	return;
}

void init_inv(int len){
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(int i=1;i<=len;++i) fac[i]=mul(fac[i-1],i);
	ifac[len]=qpw(fac[len],mod-2);
	for(int i=len-1;i;--i) ifac[i]=mul(ifac[i+1],i+1);
	for(int i=1;i<=len;++i) inv[i]=mul(ifac[i],fac[i-1]);
	return;
}

void NTT(poly &f,int sgn){
	for(int i=0;i<lim;++i)
		if(i<rev[i]) swap(f[i],f[rev[i]]);
	for(int len=1;len<lim;len<<=1){
		int siz=len<<1;
		int wn=qpw(3,(mod-1)/siz);
		for(int l=0;l<lim;l+=siz){
			int w=1;
			for(int i=l;i<l+len;++i){
				int a=f[i],b=mul(f[i+len],w);
				f[i]=add(a,b);
				f[i+len]=dec(a,b);
				w=mul(w,wn);
			}
		}
	}
	if(sgn) return;
	int INV=qpw(lim,mod-2);
	reverse(f.begin()+1,f.end());
	for(int i=0;i<lim;++i)
		f[i]=mul(f[i],INV);
	return;
}

poly operator + (poly f,poly g){
	f.resize(max(f.size(),g.size()));
	for(int i=0;i<g.size();++i)
		f[i]=add(f[i],g[i]);
	return f;
}

poly operator - (poly f,poly g){
	f.resize(max(f.size(),g.size()));
	for(int i=0;i<g.size();++i)
		f[i]=dec(f[i],g[i]);
	return f;
}

poly operator * (poly a,poly b){
	int deg=a.size()+b.size()-1;
	if(a.size()<=32||b.size()<=32){
		poly c(deg,0);
		for(int i=0;i<a.size();++i)
			for(int j=0;j<b.size();++j)
				c[i+j]=add(c[i+j],mul(a[i],b[j]));
		return c;
	}
	init(deg);
	a.resize(lim),NTT(a,1);
	b.resize(lim),NTT(b,1);
	for(int i=0;i<lim;++i) a[i]=mul(a[i],b[i]);
	NTT(a,0);
	a.resize(deg);
	return a;
}

poly operator * (poly a,int b){
	for(int i=0;i<a.size();++i)
		a[i]=mul(a[i],b);
	return a;
}

poly der(poly f){
	for(int i=0;i<f.size()-1;++i)
		f[i]=mul(f[i+1],i+1);
	f.pop_back();
	return f;
}

poly Int(poly f){
	f.pb(0);
	for(int i=f.size()-1;i;--i)
		f[i]=mul(f[i-1],inv[i]);
	f[0]=0;
	return f;
}

void divx(poly &f,int cnt){
	int deg=f.size()-cnt;
	for(int i=0;i<deg;++i) f[i]=f[i+cnt];
	f.resize(deg);
	return;
}

void mulx(poly &f,int cnt){
	int deg=f.size()+cnt;
	f.resize(deg);
	for(int i=cnt;i<deg;++i) f[i]=f[i-cnt];
	for(int i=0;i<cnt;++i) f[i]=0;
	return;
}

poly Inv(cs poly &a,int siz){
	poly c,b(1,qpw(a[0],mod-2));
	for(int len=2;(len>>1)<siz;len<<=1){
		init(len<<1);
		c=a,c.resize(len);
		c.resize(lim),NTT(c,1);
		b.resize(lim),NTT(b,1);
		for(int i=0;i<lim;++i) b[i]=mul(b[i],dec(2,mul(c[i],b[i])));
		NTT(b,0);
		b.resize(len);
	}
	b.resize(siz);
	return b;
}poly Inv(cs poly &a){return Inv(a,a.size());}

poly ln(poly a,int len){
	a=Int(der(a)*Inv(a,len));
	a.resize(len);
	return a;
}poly ln(cs poly &a){return ln(a,a.size());}

poly exp(cs poly &a,int siz){
	poly c,b(1,1);
	for(int len=2;(len>>1)<siz;len<<=1){
		c=ln(b,len);
		for(int j=0;j<len;++j) c[j]=dec(j<a.size()?a[j]:0,c[j]);
		c[0]=add(c[0],1);
		b=b*c;
		b.resize(len);
	}
	b.resize(siz);
	return b;
}poly exp(cs poly &a){return exp(a,a.size());}

poly qpw(poly a,int k,int len){
	a=exp(ln(a)*k);
	a.resize(len);
	return a;
}poly qpw(cs poly &a,int k){return qpw(a,k,a.size());}

poly sqrt(cs poly &a,int deg){
	poly b(1,1),c,d;
	for(int len=2;(len>>1)<deg;len<<=1){
		init(len<<1);
		c=a,c.resize(len);
		d=Inv(b,len);
		c=c*d;
		b.resize(len);
		for(int i=0;i<len;++i) b[i]=mul(add(c[i],b[i]),inv2);
	}
	b.resize(deg);
	return b;
}poly sqrt(cs poly &a){return sqrt(a,a.size());}

poly operator / (poly a,poly b){
	int deg=a.size()-b.size()+1;
	reverse(a.begin(),a.end());
	reverse(b.begin(),b.end());
	init(deg);
	b=Inv(b,lim);b.resize(deg);
	a=a*b;a.resize(deg);
	reverse(a.begin(),a.end());
	return a;
}

poly operator % (cs poly &a,cs poly &b){
	poly c=a-(a/b)*b;
	c.resize(b.size()-1);
	return c;
}

cs int w4=qpw(3,(mod-1)/4);
poly cos(cs poly &a,int siz){
	poly c=a;c.resize(siz);
	c=(exp(c*w4)+exp(c*(mod-w4)))*inv2;
	return c;
}poly cos(cs poly &a){return cos(a,a.size());}

poly sin(cs poly &a,int siz){
	poly c=a;c.resize(siz);
	c=(exp(c*w4)-exp(c*(mod-w4)))*mul(inv2,qpw(w4,mod-2));
	return c;
}poly sin(cs poly &a){return sin(a,a.size());}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值