首页 > 其他分享 >【笔记】多项式全家桶

【笔记】多项式全家桶

时间:2024-08-04 23:49:31浏览次数:8  
标签:int 多项式 全家 笔记 ln pmod lim equiv

【笔记】多项式全家桶

https://www.cnblogs.com/Appleblue17/p/14360752.html

Warning

  1. 空间记得开两倍,因为有卷积,最后结果是两多项式长度之和。
  2. 对于多项式 \(F(x)\),

Template

p.s. 一般函数最开始是输出数组,后接输入数组,及其长度。

namespace NTT
{
	const int gen = 3;
	int r[N];
	void ntt (int *f, int n, int sign) {
		for (int i = 0; i < n; i++)
			if (i < r[i]) swap(f[i], f[r[i]]);
		for (int mid = 1; mid < n; mid<<=1) {
			int o = qpow(gen, 1ll*sign*(mod-1)/(mid<<1)%mod+(mod-1));
			for (int i = 0; i < n; i += mid<<1)
				for (int j = 0, w = 1; j < mid; j++, w = 1ll*w*o%mod) {
					int x = f[i+j], y = 1ll*w*f[i+mid+j]%mod;
					f[i+j] = (1ll*x+y) % mod;
					f[i+mid+j] = (1ll*x-y+mod) % mod;
				}
		}
		if (sign == -1) {
			int inv_n = ::inv(n);
			for (int i = 0; i < n; i++) f[i] = 1ll*f[i]*inv_n%mod;
		}
	}
	void mul (int *c, int *a, int *b, int n, int m, int (*op)(int, int)=[](int a, int b){ return int(1ll*a*b%mod); }) {
		int lim = 1, len = 0;
		while (lim <= n+m) lim <<= 1, len++;
		for (int i = 0; i <= lim; i++)
			r[i] = (r[i>>1]>>1)|((i&1)<<(len-1));
		ntt(a, lim, 1), ntt(b, lim, 1);
		for (int i = 0; i <= lim; i++) c[i] = op(a[i],b[i]);
		ntt(c, lim, -1);
	}
} // namespace NTT
namespace Poly
{
	void derivative (int *g, int *f, int n) {
		for (int i = 1; i <= n; i++) g[i-1] = 1ll*f[i] * i % mod;
		g[n] = 0;
	}
	void integral (int *g, int *f, int n) {
		for (int i = n; i >= 1; i--) g[i] = 1ll*f[i-1] * ::inv(i) % mod;
		g[0] = 0;
	}
	void inv (int *g, int *f, int n) {
		if (n == 0) return g[0] = ::inv(f[0]), void();
		inv(g, f, n>>1);
		int lim = 1; while (lim <= n<<1) lim <<= 1;
		static int h[N];
		for (int i = 0; i <= lim; i++) h[i] = i <= n ? f[i] : 0;
		NTT::mul(g, h, g, n, n, [](int a, int b){
			return int((2ll*b%mod-1ll*b*b%mod*a%mod+mod) % mod);
		});
		for (int i = n+1; i <= lim; i++) g[i] = 0;
	}
	void ln (int *g, int *f, int n) {
		static int _f[N], inv_f[N];
		int lim = 1; while (lim <= n<<1) lim <<= 1;
		fill(_f, _f+lim+1, 0), fill(inv_f, inv_f+lim+1, 0);
		derivative(_f, f, n), inv(inv_f, f, n);
		NTT::mul(g, _f, inv_f, n, n);
		integral(g, g, n);
	}
	void exp (int *g, int *f, int n) {
		if (n == 0) return g[0] = 1, void(); // 题目保证 f 的常数项为 0
		exp(g, f, n>>1);
		int lim = 1; while (lim <= n<<1) lim <<= 1;
		static int h[N]; ln(h, g, n);
		for (int i = 0; i <= lim; i++) h[i] = i <= n ? ((1ll*(i==0)-h[i]+f[i]+mod)%mod) : 0;
		NTT::mul(g, h, g, n, n);
		for (int i = n+1; i <= lim; i++) g[i] = 0;
	}
} // namespace Poly

p.s.

  1. 所有求 lim 的时候,理论上来说 lim = n+m 的时候 lim 是不需要再倍增的,但是有 n+m = 1 的情况,这个时候 len = 0 然后就 G 了,懒得特判所以就先打等于了。
  2. NTT::mul 里面的 *a,*b 不能相同。
  3. Poly:: 里面除了 derivative(),integral(),ln()*g,*f 可以相同,其余都不能相同。
  4. Poly::inv(),exp() 中的 *g 必须是干净的。

0 前置知识

0.1 多项式求导与积分

0.1.1 求导

参见 0.3


0.1.2 积分

单项式积分为:

\[\int x^a\mathrm dx=\dfrac 1{a+1}x^{a+1} \]

多项式即为每个单项式积分再相加。对于每个单项式的系数,直接乘到最后的结果中。

1 正片开始

1.1 FFT/NTT

https://www.cnblogs.com/CloudWings/p/18005389


1.2 多项式求逆

可以直接硬推递推式,也可以上牛顿迭代。


1.3 多项式对数函数 (ln)

给定 \(F(x)\),求 \(G(x)\) 满足 \(G(x)\equiv \ln F(x)\pmod{x^n}\)。

考虑到 \(\ln^\prime x=\dfrac 1x\),我们对等式两侧求导:(注意链式法则

\[G^\prime(x)=\ln^\prime F(x)=\dfrac {F^\prime(x)}{F(x)} \]

然后再积分就得到了 \(G(x)\)。


1.4 多项式指数函数(exp)

给定 \(F(x)\),求 \(G(x)\) 满足 \(G(x)\equiv e^{F(x)}\pmod{x^n}\)。

\[G(x)\equiv e^{F(x)}\pmod{x^n}\\ \Rightarrow \ln G(x)\equiv F(x)\pmod{x^n}\\ \Rightarrow \ln (G(x))-F(x)\equiv 0\pmod{x^n} \]

然后就可以上牛顿迭代了。

假设已经求出了 \(G_0(x)\equiv e^{F(x)}\pmod{x^{\left \lceil \frac n2 \right \rceil }}\)

由牛顿迭代:(注意现在的 \(G_0(x),F(x)\) 都是已知量,所以 \(F(x)\) 当成常数,\(G_0(x)\) 这个整体当作变量来处理

\[\begin{aligned} G(x)&\equiv G_0(x)-\dfrac {\ln (G_0(x))-F(x)}{(\ln (G_0(x))-F(x))^\prime}\pmod {x^n}\\ &\equiv G_0(x)-\dfrac {\ln (G_0(x))-F(x)}{\frac1{G_0(x)}}\pmod {x^n}\\ &\equiv G_0(x)(1-\ln (G_0(x))+F(x))\pmod {x^n}\\ \end{aligned} \]


1.5 多项式带余除法

给定 \(F(x),G(x)\)(项数分别为 \(n,m\)),求 \(Q(x),R(x)\)。满足:\(F(x)=G(x)Q(x)+R(x)\),且 \(Q(x)\) 的项数为 \(n-m\),\(R(x)\) 的项数小于 \(m\)。

现在问题主要在于,我们同时有两个待求的多项式。

一个很神奇的手法是,将这些多项式都翻转,严格的定义是:

\[\mathrm{rev}(F(x))=x^nF(x^{-1}) \]

于是可以推出:(过程可以参考开头的博客。

标签:int,多项式,全家,笔记,ln,pmod,lim,equiv
From: https://www.cnblogs.com/CloudWings/p/18342433

相关文章

  • SA 学习笔记
    SA的定义一个字符串有\(n\)个后缀,把\(n\)个后缀按字典序排序,得到数组\(sa\)。\(sa\)的每一个元素是每个后缀的第一个字符的index。\(rk\)数组代表了原先的每个后缀在排序后的位置。例如:eaabd,其后缀为eaabdaabdabdbdd,排序后为aabdabdbddeaabd,\(sa=\{2,3,4,......
  • day1-Django笔记
    1.手动创建Django项目(初学则推荐)创建一个python虚拟环境>=3.61.win+r进入终端2.condaenvlist#查看有哪些虚拟环境3.condacreate--namepy36_netpython==3.6#创建一个python环境4.activate虚拟环境名#激活虚拟环境5.condadeactivate#退出虚拟环境安装dja......
  • Python基础算法笔记
    整理自B站视频https://www.bilibili.com/video/BV1uA411N7c5递归1.汉诺塔问题#n个圆盘,从a经过b移动到cdefhanoi(n,a,b,c):ifn>0:#将n-1个圆盘从a经过c移动到bhanoi(n-1,a,c,b)#将最底层的圆盘从a移动到cprint("mov......
  • 优化蒙特卡洛算法笔记1
    fromkaiwu_agent.utils.common_funcimportcreate_cls,attachedSampleData=create_cls("SampleData",state=None,action=None,reward=None)ObsData=create_cls("ObsData",feature=None)ActData=create_cls("ActData",ac......
  • 学习笔记第十七天
    1.Shell基本语法    1.注释:以#符号开始,直到行末,用于解释代码或暂时禁用某行代码。    2.命令:如echo、ls等,用于执行系统命令或调用外部程序。    3.控制结构:包括if语句、for循环、while循环等,用于控制脚本的流程。2.创建和执行脚本    1.......
  • 《802.11无线网络权威指南-无线网络导论》-- 读书笔记1
    专业术语发射塔:celltower,指信号发射塔基站,接入点:accesspoint无线数据网络:wirelessdatanetwork基站:basestationauthorization:授权,认证serviceprovider:服务供应商hotspot:热点WAN:广域网络infraredlight:红外线频带:frequencyband带宽:bandwidth,即可供使用的频率......
  • KMP学习笔记
    KMP一种字符串单模匹配算法。原理当模式串\(s\)与文本串\(t\)进行匹配时,容易想到的一种朴素做法就是将模式串的第一位与文本串的每一位进行试配。但是这样效率过低,容易被数据卡成\(O(n^2)\)。KMP单模匹配算法引入了一个失配数组border。定义一个字符串的border为一......
  • QT 笔记
     HTTPSSSL配置下载配置子父对象QTimer*timer=newQTimer;//QTimerinheritsQObjecttimer->inherits("QTimer");//returnstruetimer->inherits("QObject");//returnstruetimer->inherits("QAbstractBut......
  • 【学习笔记】哈希
    【学习笔记】哈希Hash的核心思想在于,将输入映射到一个值域较小、可以方便比较的范围。主要用来判重!如何辨别哈希题?大概就通过一句话:当需要用\(O(1)\)的时间快速比较两个\(O(n)\)的东西时。应该对大部分题目都生效。字符串哈希感觉这一块OI_wiki讲得比较清楚。通常我......
  • UE5学习笔记3-关于charactor的相机和弹簧臂组件
    一、环境说明,UE5.4+ vs2022 +win11二、相机和弹簧臂的作用    个人理解上,相机的作用相当于一个视角,我将其理解成是一个人在哪个地方朝向哪个方向看,弹簧臂的用用我将其理解成为一个将人的视角和人物模型或其他模型连接的桥梁三、相机和弹簧臂的代码    ......