首页 > 其他分享 >多项式小全家桶

多项式小全家桶

时间:2023-08-28 17:02:12浏览次数:30  
标签:int 多项式 全家 len ++ lim mul mod

比较安全的模板,传入的数组 \(g\) 有初值也没有问题,且求解过程中不会对传入的 \(f\) 修改

#include <bits/stdc++.h>
using namespace std;
const int N = 1 << 17;
const int mod = 998244353;

bool mem1;
char buf[1 << 23], *p1 = buf, *p2 = buf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1 ++)
int read() {
    int s = 0, w = 1; char ch = getchar();
    while(!isdigit(ch)) { if(ch == '-') w = -1; ch = getchar(); }
    while(isdigit(ch)) { s = s * 10 + (ch ^ 48), ch = getchar(); }
    return s * w;
}

template <typename A> int mul(A x) { return x; }
template <typename A, typename ...B> int mul(A x, B ...args) { return 1ll * x * mul(args ...) % mod; }
void inc(int &a, int b) { a = a >= mod - b ? a - mod + b : a + b; }
int ksm(int a, int b) {
	int res = 1;
	while(b > 0) {
		if(b & 1) res = mul(res, a);
		a = mul(a, a), b >>= 1;
	}
	return res;
}

int f[N], g[N], rev[N], iv[N];
int inv2 = ksm(2, mod - 2), inv3 = ksm(3, mod - 2);

void ntt(int *f, int op, int len) {
	for(int i = 0; i < len; ++ i)
		if(i < rev[i]) swap(f[i], f[rev[i]]);
	for(int i = 2; i <= len; i <<= 1) {
		int base = ksm(op == 1 ? 3 : inv3, (mod - 1) / i);
		for(int j = 0, p = i >> 1; j < len; j += i) 
			for(int k = 0, pw = 1; k < p; ++ k) {
				int x = f[j + k], y = mul(pw, f[j + k + p]);

				f[j + k] = (x + y) % mod, f[j + k + p] = (x - y + mod) % mod;
				pw = mul(pw, base);
			}
	}
	if(op == -1)
		for(int i = 0, inv = ksm(len, mod - 2); i < len; ++ i)
			f[i] = mul(f[i], inv);
}

int f_in[N], g_in[N];
void inv(int *f, int *g, int n) {
	int len;
	g[0] = ksm(f[0], mod - 2);
	for(len = 1; len < (n << 1); len <<= 1) {
		int lim = (len << 1);
		for(int i = 0; i < len; ++ i) g_in[i] = g[i], f_in[i] = f[i];

		for(int i = 0; i < lim; ++ i)
			rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * len);
		ntt(f_in, 1, lim), ntt(g_in, 1, lim);
		for(int i = 0; i < lim; ++ i)
			f_in[i] = mul(g_in[i], (2ll - mul(f_in[i], g_in[i]) + mod) % mod);
		ntt(f_in, -1, lim);
		
		for(int i = 0; i < lim; ++ i) g[i] = f_in[i];
		for(int i = len; i < lim; ++ i) g[i] = 0;
	}
	for(int i = n; i < len; ++ i) g[i] = 0;
	for(int i = 0; i < len; ++ i) f_in[i] = g_in[i] = 0;
}

int f_sq[N], g_sq[N];
void sqrt(int *f, int *g, int n) {
	int len;
	g[0] = 1;
	for(len = 1; len < (n << 1); len <<= 1) {
		int lim = (len << 1);
		for(int i = 0; i < len; ++ i) f_sq[i] = f[i];
		inv(g, g_sq, len);

		for(int i = 0; i < lim; ++ i) 
			rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * len);
		ntt(f_sq, 1, lim), ntt(g_sq, 1, lim);
		for(int i = 0; i < lim; ++ i) f_sq[i] = mul(f_sq[i], g_sq[i]);
		ntt(f_sq, -1, lim);

		for(int i = 0; i < lim; ++ i) g[i] = mul((f_sq[i] + g[i]) % mod, inv2);
		for(int i = len; i < lim; ++ i) g[i] = 0;
	}
	for(int i = n; i < len; ++ i) g[i] = 0;
	for(int i = 0; i < len; ++ i) f_sq[i] = g_sq[i] = 0;
}

void deriv(int *f, int *g, int n) {
	for(int i = 0; i < n; ++ i)
		g[i] = mul(i + 1, f[i + 1]);
	g[n - 1] = 0;
}
void inter(int *f, int *g, int n) {
	for(int i = n - 2; i >= 0; -- i)
		g[i + 1] = mul(f[i], iv[i + 1]);
	g[0] = 0;
}

int f_ln[N], g_ln[N];
void ln(int *f, int *g, int n) {
	deriv(f, f_ln, n);
	inv(f, g_ln, n);
	
	int lim = 1, bit = 0;
	while(lim <= 2 * n - 2) lim <<= 1, ++ bit;

	for(int i = 0; i < lim; ++ i)
		rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1);
	ntt(f_ln, 1, lim), ntt(g_ln, 1, lim);
	for(int i = 0; i < lim; ++ i)
		f_ln[i] = mul(f_ln[i], g_ln[i]);
	ntt(f_ln, -1, lim);
	for(int i = 0; i < n; ++ i) g[i] = f_ln[i];
	for(int i = 0; i < lim; ++ i) f_ln[i] = g_ln[i] = 0;

	inter(g, g, n);
}

int f_ex[N], g_ex[N];
void exp(int *f, int *g, int n) {
	int len;
	g[0] = 1;
	for(len = 1; len < (n << 1); len <<= 1) {
		int lim = (len << 1);
		ln(g, g_ex, len);
		for(int i = 0; i < len; ++ i)
			f_ex[i] = g[i], g_ex[i] = (f[i] - g_ex[i] + mod) % mod;
		++ g_ex[0];

		for(int i = 0; i < lim; ++ i) 
			rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * len);
		ntt(f_ex, 1, lim), ntt(g_ex, 1, lim);
		for(int i = 0; i < lim; ++ i) f_ex[i] = mul(f_ex[i], g_ex[i]);
		ntt(f_ex, -1, lim);
		
		for(int i = 0; i < lim; ++ i) g[i] = f_ex[i];
		for(int i = len; i < lim; ++ i) g[i] = 0;
	}
	for(int i = n; i < len; ++ i) g[i] = 0;
	for(int i = 0; i < len; ++ i) f_ex[i] = g_ex[i] = 0;
}

int n, m;

bool mem2;
signed main() {
	cerr << (&mem2 - &mem1) / 1048576. << endl;
	iv[0] = iv[1] = 1;
	for(int i = 2; i < N; ++ i)
		iv[i] = mul(mod - mod / i, iv[mod % i]);

	n = read();
	for(int i = 0; i < n; ++ i) f[i] = read();
	exp(f, g, n);
	for(int i = 0; i < n; ++ i) printf("%d ", g[i]);
	return 0;
}

标签:int,多项式,全家,len,++,lim,mul,mod
From: https://www.cnblogs.com/wyb-sen/p/17662792.html

相关文章

  • 用单链表实现一元多项式相加 C++代码
     #include<iostream>usingnamespacestd;/*结点的定义*/typedefstructLNode{floatcoef;intexp;structLNode*next;}LNode;typedefLNode*Polynomial;/*多项式的初始化*/voidinitDuoX(Polynomial&Px){Px=newLNode;......
  • lr下载-中文官版下载网址adobe全家桶软件下载 中文版直装
    Lr6.0中文版是一款出自Adobe公司之手的实用型照片编辑管理工具,Lr6.0中文版功能强劲,为数码摄影、图形设计等专业用户提供了强大数码相片浏览、编辑、整理、打印等功能,AdobeLightroom6.0中文版能够帮助用户轻松的管理大型照片图库。软件地址:看置顶贴版本功能Lr6.0中文版附带全新......
  • 多项式乘法逆
    问题:给定一个多项式\(F(x)\),请求出一个多项式\(G(x)\),满足\(F(x)*G(x)\equiv1\pmod{x^n}\)。系数对\(998244353\)取模。考虑分治,假设我们已经求出多项式\(F(x)\)在\(\bmodx^{\lceil\frac{n}{2}\rceil}\)时的逆\(G'(x)\)。有:\[F(x)*G'(x)\equiv1(\bmodx......
  • 多项式模板
    //#defineFFT_//#defineFAST//#defineSECURE#ifdefFFT_#ifdefFAST#defineFAST_FAST_TLE_#endif#ifdefSECURE#defineHIGH_PRECISION#endif#endif#ifdefFAST#include<bits/extc++.h>#endifnamespaceMath{ constintP=998244353,G=3,Gi=33274811......
  • Matlab 多项式的根求解
    ✅作者简介:热爱科研的算法开发者,Python、Matlab项目可交流、沟通、学习。......
  • Vue全家桶系~2.Vue3开篇(过渡)
    Vue全家桶先贴一下Vue3的官方文档:https://cn.vuejs.org/guide/introduction.html官方API文档:https://cn.vuejs.org/api/1.前言:新旧时代交替1.1.开发变化1.网络模型的变化:以前网页大多是b/s,服务端代码混合在页面里;现在是c/s,前后端分离,通过jsapi(类似ajax的方式)获取j......
  • 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(13):Hamliton-Cay
    目录前言Hello!小伙伴!非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ 自我介绍ଘ(੭ˊᵕˋ)੭昵称:海轰标签:程序猿|C++选手|学生简介:因C语言结识编程,随后转入计算机专业,有幸拿过一些国奖、省奖…已保研。目前正在学习C++/Linux/Python学习经验:扎实基础+多做笔记+......
  • 数论全家桶
    数论全家桶目录数论全家桶欧拉定理中国剩余定理CRTEXCRTLUCAS定理卡特兰数欧拉定理1.结论$$∀a,m∈Z且gcd(a,m)=1,a^{\varphi(m)}\equiv1\(mod\m)$$欧拉定理的一个常见用法是对指数降幂。应用当mod数质数时,有$$a^b\equiva^{bmod\phi(m)} (modm), gcd(a,m)=1;$$例......
  • 7-18 二分法求多项式单根 (20分)
    7-18 二分法求多项式单根 (20分)二分法求函数根的原理为:如果连续函数f(x)在区间[a,b]的两个端点取值异号,即f(a)f(b)<0,则它在这个区间内至少存在1个根r,即f(r)=0。二分法的步骤为:检查区间长度,如果小于给定阈值,则停止,输出区间中点(a+b)/2;否则如果f(a)f(b)<0,则计算中点的值f((a+b)/2)......
  • 多项式小记
    先粘个\(\rmNTT\)和\(\rmFFT\)的板子。inlinevoidtimes(LL*f,LL*g,intn,intlim){ intkn=initr(n);NTT(f,kn,1);NTT(g,kn,1); for(inti=0;i<kn;i++)f[i]=f[i]*g[i]%Mod; NTT(f,kn,-1);NTT(g,kn,-1); clr(f,lim,kn);}分治\(NTT/FFT\)大概就是维护下面......