首页 > 其他分享 >多项式板子

多项式板子

时间:2024-02-29 21:57:37浏览次数:21  
标签:int 多项式 NTT len 板子 ull ans mod

#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int N=262150,mod=998244353,g=3,invg=(mod+1)/3,inv2=(mod+1)/2;
int rev[N];
ull a[N],b[N],w[N],inv[N];
int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1){
			ans=1ll*ans*a%mod;
		}
		a=1ll*a*a%mod;
		b>>=1;
	}
	return ans;
}
void CLR(ull *a,int n){
	for(int i=0;i<=n-1;i++){
		a[i]=0;
	}
}
void CPY(ull *a,ull *b,int n){
	for(int i=0;i<=n-1;i++){
		a[i]=b[i];
	}
}
void INIT(int lim){
	for(int i=0;i<lim;i++){
		rev[i]=(rev[i>>1]>>1)|((i&1)?lim>>1:0);
	}
}
void REV(ull *a,int n){
	reverse(a,a+n);
}
void ADD(ull *a,ull *b,int n){
	for(int i=0;i<=n-1;i++){
		a[i]=(a[i]+b[i])%mod;
	}
}
void DEC(ull *a,ull *b,int n){
	for(int i=0;i<=n-1;i++){
		a[i]=(a[i]-b[i]+mod)%mod;
	}
}
void DRV(ull *a,int n){
	for(int i=0;i<=n-1;i++){
		a[i]=a[i+1]*(i+1)%mod;
	}
}
void ITG(ull *a,int n){
	for(int i=n-1;i>=1;i--){
		a[i]=a[i-1]*inv[i]%mod;
	}
	a[0]=0;
}
void NTT(ull *a,int lim,int op){
	ull x,y;
	int r;
	for(int i=0;i<lim;i++){
		if(i<rev[i]){
			swap(a[i],a[rev[i]]);
		}
	}
	w[0]=1;
	for(int mid=1;mid<lim;mid<<=1){
		r=mid<<1;
		x=qpow(op==1?g:invg,(mod-1)/r);
		for(int j=1;j<mid;j++){
			w[j]=w[j-1]*x%mod;
		}
		for(int j=0;j<lim;j+=r){
			for(int k=j;k-j<mid;k++){
				x=a[k];
				y=a[k+mid]%mod*w[k-j]%mod;
				a[k]=x+y;
				a[k+mid]=x-y+mod;
			}
		}
		if(mid==(1<<18)){
			for(int j=0;j<lim;j++){
				a[j]%=mod;
			}
		}
	}
	for(int i=0;i<lim;i++){
		a[i]%=mod;
	}
}
void CROSS(ull *a,ull *b,int n){
	for(int i=0;i<=n-1;i++){
		a[i]=a[i]*b[i]%mod;
	}
}
void MUL(ull *a,ull *b,int n){
	int lim=1,invv;
	while(lim<n){
		lim<<=1;
	}
	invv=qpow(lim,mod-2);
	INIT(lim);
	NTT(a,lim,1);
	if(a!=b){
		NTT(b,lim,1);
	}
	CROSS(a,b,lim);
	NTT(a,lim,-1);
	for(int i=0;i<lim;i++){
		a[i]=a[i]*invv%mod;
	}
	CLR(a+n,lim-n-1);
	if(a!=b){
		CLR(b,lim);
	}
}
void INV(ull *a,ull *b,int n){
	int lim=1,l=0,invv;
	static ull c[N],d[N];
	b[0]=qpow(a[0],mod-2);
	while(lim<n){
		lim<<=1;
		l++;
	}
	for(int len=2;len<=lim;len<<=1){
		CLR(c+(len>>1),len>>1);
		CPY(c,b,len>>1);
		CPY(d,a,len);
		INIT(len);
		NTT(c,len,1);
		NTT(d,len,1);
		CROSS(d,c,len);
		NTT(d,len,-1);
		invv=qpow(len,mod-2);
		for(int i=0;i<len;i++){
			d[i]=d[i]*invv%mod;
		}
		CLR(d,len>>1);
		NTT(d,len,1);
		CROSS(d,c,len);
		NTT(d,len,-1);
		for(int i=len>>1;i<len;i++){
			b[i]=mod-d[i]*invv%mod;
		}
	}
	for(int i=0;i<lim;i++){
		b[i]%=mod;
	}
	CLR(b+n,lim-n-1);
}
int BSGS(int b,int n,int mod){
	int t=sqrt(mod)+1,now=1;
	unordered_map<int,int>mapp;
	for(int bb=0;bb<=t-1;bb++){
		mapp[1ll*now*n%mod]=bb;
		now=1ll*now*b%mod;
	}
	b=now;
	now=1;
	for(int aa=1;aa<=t;aa++){
		now=1ll*now*b%mod;
		if(mapp.count(now)){
			return aa*t-mapp[now];
		}
	}
	return -1;
}
void SQRT(ull *a,ull *b,int n){
	int lim=1,l=0;
	static ull c[N],d[N];
	b[0]=qpow(g,BSGS(g,a[0],mod)/2);
	b[0]=min(b[0],mod-b[0]);
	while(lim<n){
		lim<<=1;
		l++;
	}
	for(int len=2;len<=lim;len<<=1){
		CPY(c,b,len);
		CLR(d,len);
		INV(c,d,len);
		CLR(c,len);
		CPY(c,a,len);
		MUL(c,d,len<<1);
		ADD(b+(len>>1),c+(len>>1),len>>1);
		for(int i=len>>1;i<len;i++){
			b[i]=b[i]*inv2%mod;
		}
	}
}
void DIV(ull *a,ull *b,int n,int m){
	static ull c[N],d[N];
	REV(a,n);
	REV(b,m);
	CPY(c,b,n-m+1);
	INV(c,d,n-m+1);
	CPY(c,a,n-m+1);
	MUL(c,d,(n-m+1)<<1);
	CLR(c+n-m+1,n-m+1);
	REV(c,n-m+1);
	CPY(d,c,n-m+1);
	REV(a,n);
	REV(b,m);
	MUL(c,b,n<<1);
	CLR(c+n,n);
	DEC(a,c,n);
	CPY(b,a,m-1);
	CPY(a,d,n-m+1);
}
void LN(ull *a,ull *b,int n){
	static ull c[N];
	CPY(b,a,n);
	DRV(b,n);
	INV(a,c,n);
	MUL(b,c,n<<1);
	CLR(b+n,n);
	ITG(b,n);
}
void EXP(ull *a,ull *b,int n){
	int lim=1;
	static ull c[N],d[N];
	b[0]=1;
	while(lim<n){
		lim<<=1;
	}
	for(int len=2;len<=lim;len<<=1){
		CPY(c,b,len);
		CLR(d,len);
		LN(c,d,len);
		CLR(c,len);
		c[0]=1;
		DEC(c,d,len);
		ADD(c,a,len);
		MUL(b,c,len<<1);
		CLR(b+len,len);
		CLR(c+len,len);
	}
}
void POW(ull *a,int n,int k){
	static ull b[N];
	LN(a,b,n);
	for(int i=0;i<=n-1;i++){
		b[i]=b[i]*k%mod;
	}
	CLR(a,n);
	EXP(b,a,n);
	CLR(b,n);
}
void SIN(ull *a,ull *b,int n){
	int ii;
	static ull c[N],d[N]; 
	CPY(c,a,n);
	ii=qpow(g,BSGS(g,mod-1,mod)/2);
	for(int i=0;i<=n-1;i++){
		c[i]=c[i]*ii%mod;
	}
	EXP(c,b,n);
	CPY(d,b,n);
	CLR(c,n);
	INV(d,c,n);
	DEC(b,c,n);
	ii=qpow(ii,mod-2);
	for(int i=0;i<=n-1;i++){
		b[i]=b[i]*inv2%mod*ii%mod;
	}
}
void COS(ull *a,ull *b,int n){
	int ii;
	static ull c[N],d[N];
	CPY(c,a,n);
	ii=qpow(g,BSGS(g,mod-1,mod)/2);
	for(int i=0;i<=n-1;i++){
		c[i]=c[i]*ii%mod;
	}
	EXP(c,b,n);
	CPY(d,b,n);
	CLR(c,n);
	INV(d,c,n);
	ADD(b,c,n);
	for(int i=0;i<=n-1;i++){
		b[i]=b[i]*inv2%mod;
	}
}
void ARCSIN(ull *a,ull *b,int n){
	static ull c[N],d[N];
	CPY(b,a,n);
	DRV(b,n);
	CPY(c,a,n);
	MUL(c,c,n<<1);
	CLR(c+n,n);
	d[0]=1;
	DEC(d,c,n);
	CLR(c,n);
	SQRT(d,c,n);
	CLR(d,n);
	INV(c,d,n);
	MUL(b,d,n<<1);
	CLR(b+n,n);
	ITG(b,n);
	CLR(c,n<<1);
	CLR(d,n);
}
void ARCTAN(ull *a,ull *b,int n){
	static ull c[N],d[N];
	CPY(b,a,n);
	DRV(b,n);
	CPY(c,a,n);
	MUL(c,c,n<<1);
	CLR(c+n,n);
	d[0]=1;
	ADD(d,c,n);
	CLR(c,n);
	INV(d,c,n);
	MUL(b,c,n<<1);
	CLR(b+n,n);
	ITG(b,n);
	CLR(c,n<<1);
	CLR(d,n);
}
int main(){
	inv[1]=1;
	for(int i=2;i<=n;i++){
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	}
	//do something...
}

标签:int,多项式,NTT,len,板子,ull,ans,mod
From: https://www.cnblogs.com/zhicheng123/p/18045596

相关文章

  • SC的个人板子库
    声明Sugar_Cube的博客园主页宇宙安全声明本文包含了笔者常用的OI算法、数据结构的模板不保证正确,但能通过相应的模板题(如果有会挂出)如有错误请在评论区指出(虽然大抵没人看就是了)码风是笔者的个人习惯(能看懂就好喵),部分代码可能会省略快读Read()持续更新咕咕咕输入输出优化......
  • 【模板】任意模数多项式乘法
    题目描述给定\(2\)个多项式\(F(x),G(x)\),请求出\(F(x)\timesG(x)\)。系数对\(p\)取模,且不保证\(p\)可以分解成\(p=a\cdot2^k+1\)之形式。题解可以用快速数论变换NTT算法,关键在于取的那个素数。由于系数最大为\(10^5\times10^{9+9}=10^{23}\)所以可以......
  • 多项式模板整理
    约定\(F[i]\)表示\(F(x)\)的\(i\)次项系数。多项式乘法基础详情见多项式乘法入门多项式求逆给出\(n\)次多项式\(F(x)\),求一个多项式\(G(x)\),满足\(F(x)G(x)\equiv1\pmod{x^n}\),\(G(x)\)每个系数对\(998244353\)取模。我们逐一递推,假设已知\(G[1...i-1]\),需......
  • 多项式小寄
    多项式小记目录目录多项式小记目录序什么是多项式多项式四则运算加法减法乘法除法\(FFT\)多项式的点值表达\(DFT\)单位根算法原理核心流程代码\(IDFT\)结论证明代码最后的实现融融没用的常数优化蝴蝶变换递归变递推(迭代)三步变两步破除封建迷信最终代码\(NTT\)咋来的原根定义性......
  • 多项式初步
    多项式初步目录多项式初步自己写的分治FFT/NTTPart1分治FFT/NTTPart2①.多项式求逆:②.多项式带余除法:③.多项式开根:④.多项式对数:⑤.多项式exp:⑥.多项式快速幂:模板基础操作MTT自己写的分治FFT/NTTPart1给定序列\(g_{1\dotsn-1}\),求序列\(f_{0\dotsn-1}\)。其中......
  • 数学:多项式
    拉格朗日插值快速傅里叶变换(FFT)已经不知道被这玩意劝退了多少次了。但理解之后其实不算很阴间的东西?前置知识多项式负数单位根快速傅里叶变换快速傅里叶逆变换快速数论变换(NTT/FNTT)前置知识FFT注意到FFT的运算到处都是又\(\cos\)又\(\sin\)的,有不小的精度问题......
  • 一些板子
    **本博客由[@Nihachu](https://www.luogu.com.cn/user/1109610#main)的博客~~抄袭~~搬运而来**(绝大部分代码来自[@Nihachu的博客](https://www.luogu.com.cn/blog/Nihachu-33/mu-ban-ji-he)~~若有侵权,就算联系我也不会删除~~)一、二叉树相关:1、深度优先:前序遍历(根,左子树,右子......
  • 线段树(板子)
    线段树单点修改,单点,区间查询区间修改,单点,区间查询单点修改普通线段树code#definels(rt<<1)#definers(rt<<1|1)#definellllonglongconstintN=1000001;intn,m;inta[N];structT{ intl,r,data;}tr[N<<2];voidpushup(intrt){ tr[rt].da......
  • 嵌入式学习(五)要买的板子
    51单片机:arduinomicro板子加上外围才20+,很便宜冯诺依曼结构的瓶颈:由于存储器速度很慢,CPU只能被迫等待存储器读写数据,因此遏制了CPU的吞吐量,限制了计算机速度。冯·诺依曼瓶颈的概念最早由JohnBackus在1977年的图灵奖领奖演讲中提出:由于CPU和存储器之间共享同一个系统总......
  • 【多项式】任意模数 NTT/FTT
    现在有两个整数多项式\(A\),\(B\),\(0\lea_i,b_i\le10^9\),\(n\le10^5\),求它们的卷积,同时系数对\(p\le10^9\)取模。我们会发现,最终的系数可能会达到\(10^5\times10^9\times10^9=10^{23}\)级别,FFT会爆longdouble的精度;NTT,由于模数无特殊性质,完全不能使用。接......