「学习笔记」多项式相关
序
学多项式也有好久了,可是我自己还没怎么认认真真推过柿子,导致啥都不会,然后被吊打。
看来再不回顾一下就不行了啊。
多项式乘法
写了一个好看一点的\(\mathrm{NTT}\)板子,仅供参考。
inline int Add(int x, int y) { return (x + y) % Mod; }
inline int Sub(int x, int y) { return (x - y + Mod) % Mod; }
inline int Mul(int x, int y) { return 1ll * x * y % Mod; }
int fastpow(int x, int y)
{int ans = 1;for (; y; y >>= 1, x = 1ll * x * x % Mod)if (y & 1) ans = 1ll * ans * x % Mod;return ans;
}int r[maxn], w[maxn];
void FFT(int *p, int N)
{for (int i = 0; i < N; i++) if (i < r[i]) std::swap(p[i], p[r[i]]);for (int i = 1, s = 2, t = N >> 1; i < N; i <<= 1, s <<= 1, t >>= 1)for (int j = 0; j < N; j += s) for (int k = 0, o = 0; k < i; ++k, o += t){int x = p[j + k], y = 1ll * w[o] * p[i + j + k] % Mod;p[j + k] = (x + y) % Mod, p[i + j + k] = (x - y + Mod) % Mod;}
}template<typename C>
void PolyMul(int *a, int *b, int N, int P, C cal)
{w[0] = 1, w[1] = fastpow(3, (Mod - 1) / N);for (int i = 0; i < N; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << P);for (int i = 2; i < N; i++) w[i] = 1ll * w[i - 1] * w[1] % Mod;FFT(a, N), FFT(b, N); for (int i = 0; i < N; i++) b[i] = cal(a[i], b[i]);FFT(b, N); std::reverse(b + 1, b + N); int invn = fastpow(N, Mod - 2);for (int i = 0; i < N; i++) b[i] = 1ll * b[i] * invn % Mod;
}
泰勒展开
如果\(f(x)\)在\(x_0\)处存在\(n\)阶导,那么有:
\[ f(x) = \sum_{i=0}^n \frac {f^{(i)}(x_0)} {i!} (x - x_0) ^ i + \xi \]
其中\(\xi\)是余项,当\(n\)趋近于无穷大时,\(\xi\)趋近于高阶无穷小。
比如说\(e ^ x = 1 + \frac x{1!} + \frac {x^2}{2!} + \cdots\)
牛顿迭代
首先可以知道多项式的任何一个运算都可以表示成对于一个多项式\(B(x)\)以及一个给定的函数\(F(x)\),求\(F(B(x)) \equiv 0 \pmod {x ^ n}\)
设\(B_n(x)\)表示当模数是\(x ^ n\)的合法解。那么当\(n = 1\)是我们很容易可以得到结果,考虑如何用\(B_n(x)\)推到\(B_{2n}(x)\)。
对\(F(B_{2n}(x))\)在\(B_n(x)\)处泰勒展开,我们得到\(F(B_{2n}(x)) = F(B_n(x)) + F'(B_n(x))(B_{2n}(x) - B_n(x))\)。
那么我们化简一下就是:
\[ B_{2n}(x) = B_n(x) - \frac {F(B_n(x))} {F'(B_n(x))} \]
这样我们就可以倍增求解。
多项式运算
接下来均假设我们要做运算的多项式是\(A(x)\)。
多项式求逆
令\(F(B_n(x)) = A(x) * B_n(x) - 1 \equiv 0\)
于是:
\[ \begin{aligned} B_{2n} &= B_n(x) - \frac {A(x) * B_n(x) - 1} {A(x)} \\ &= B_n(x) - B_n(x)(A(x) * B_n(x) - 1) \\ &= 2B_n(x) - A(x) * B_n^2(x) \end{aligned} \]
注意第一步推到第二步是因为\(B_n(x)\)是\(A(x)\)的逆。
void Inv(int *a, int *b, int N)
{static int c[maxn]; if (N == 1) return (void) (*b = fastpow(*a, Mod - 2));Inv(a, b, (N + 1) >> 1); int L = 1, P = -1; while (L < (N << 1)) L <<= 1, ++P;std::copy(a, a + N, c), std::fill(c + N, c + L, 0);PolyMul(c, b, L, P, [] (int a, int b) { return Mul(Sub(2, Mul(a, b)), b); });std::fill(b + N, b + L, 0);
}
多项式开根
ln一下再exp一下
令\(F(B_n(x)) = B_n^2(x) - A(x) \equiv 0\)
于是有:
\[ B_{2n} = B_n(x) - \frac {B_n^2(x) - A(x)} {2B_n(x)} = \frac 12\left(B_n(x) + \frac {A(x)} {B_n(x)} \right) \]
可以看出多项式开根中需要套用多项式求逆。
void Sqrt(int *a, int *b, int N)
{static int c[maxn], d[maxn]; if (N == 1) return (void) (*b = 1);Sqrt(a, b, (N + 1) >> 1); int L = 1, P = -1; while (L < (N << 1)) L <<= 1, ++P;std::copy(a, a + N, c), std::fill(c + N, c + L, 0);std::fill(d, d + L, 0), Inv(b, d, N), PolyMul(c, d, L, P, Mul);for (int i = 0; i < N; i++) b[i] = Mul(Add(b[i], d[i]), 499122177);
}
多项式\(\ln\)
不需要牛顿迭代。
\[ \begin{aligned} \ln(A(x)) &= B(x) \\ \Rightarrow\frac {A'(x)}{A(x)} &= B'(x) \end{aligned} \]
然后\(A(x)\)就求导求逆,乘起来再积分一下就可以了。
void Ln(int *f, int *g, int N)
{static int A[maxn], B[maxn]; Inv(f, B, N), A[N - 1] = 0;for (int i = 1; i < N; i++) A[i - 1] = Mul(f[i], i);int L = 1, P = -1; while (L < (N << 1)) L <<= 1, ++P;PolyMul(A, B, L, P, Mul), g[0] = 0;for (int i = 1; i < N; i++) g[i] = Mul(B[i - 1], fastpow(i, Mod - 2));std::fill(A, A + L, 0), std::fill(B, B + L, 0);
}
多项式\(\exp\)
令\(F(B_n(x)) = \ln(B_n(x)) - A(x) \equiv 0\)
推下式子可得:
\[ \begin{aligned} B_{2n}(x) &= B_n(x) - \frac {\ln(B_n(x)) - A(x)} {\frac 1 {B_n(x)}} \\ &= B_n(x)(1 - \ln(B_n(x)) + A(x)) \end{aligned} \]
void Exp(int *a, int *b, int N)
{static int c[maxn]; if (N == 1) return (void) (*b = 1);Exp(a, b, (N + 1) >> 1), Ln(b, c, N);int L = 1, P = -1; while (L < (N << 1)) L <<= 1, ++P;for (int i = 0; i < N; i++) c[i] = Sub(a[i], c[i]); c[0] = Add(c[0], 1);PolyMul(c, b, L, P, Mul), std::fill(b + N, b + L, 0);
}
多项式除法
给定一个\(n\)次多项式\(A(x)\)和一个\(m\)次多项式\(B(x)\),求解一个\(n - m\)次的多项式\(Q(x)\)以及一个小于\(n - m\)次的多项式\(R(x)\),使得\(A(x) = Q(x)B(x) + R(x)\)
定义运算\(R\)使得\(A^R(x) = x ^ nA(\frac 1x)\),也就是说将\(A(x)\)的系数翻转。
那么可以得到:
\[ \begin{aligned} A(x) &= Q(x)B(x) + R(x) \\ A\left(\frac 1x\right) &= Q\left(\frac 1x\right)B\left(\frac 1x\right) + R\left(\frac 1x\right) \\ x ^ nA\left(\frac 1x\right) &= \left(x ^ m B\left(\frac 1x\right)\right) * \left( x ^ {n - m} Q\left(\frac 1x\right)\right) + x ^ n R\left(\frac 1x\right) \\ A^R(x) &= Q^R(x)B^R(x) + x^{n-m+1}R^R(x) \\ A^R(x) &\equiv Q^R(x)B^R(x) \pmod{x ^ {n - m + 1}} \\ Q^R(x) &\equiv \frac {A^R(x)} {B^R(x)} \pmod{x ^ {n - m + 1}} \end{aligned} \]
那么这样就可以用多项式求逆求出\(Q\),再用\(R(x) = A(x) - Q(x)B(x)\)即可求出\(R\)。
转载于:https://www.cnblogs.com/cj-xxz/p/11166903.html
「学习笔记」多项式相关相关推荐
- 「学习笔记」多项式的蛇皮操作
文章目录 「学习笔记」多项式的蛇皮操作 前置知识 趋近 自然常数 对数 逆元 导函数 牛顿迭代与泰勒公式 不定积分与定积分 多项式乘法 多项式求逆元 多项式除法/取模 多项式牛顿迭代法 多项式开根 「 ...
- 「学习笔记」黑马面面布局开发
「学习笔记」黑马面面布局开发 黑马面面布局开发 一.目的 1.1 技术方案 1.2 代码规范 1.2 目录规范 二.流程开发 2.1 蓝湖/摹客协作平台 2.2 适配方案 2.3 初始化文件 2.4 ...
- 「学习笔记」移动Web开发之flex布局9
「学习笔记」移动Web开发之flex布局9 一.flex布局体验 1.1 传统布局与flex布局 1.2 初体验 二.flex布局原理 2.1 布局原理 三.flex布局父项常见属性 3.1 常见父项 ...
- 「学习笔记」移动Web开发之rem适配布局10
「学习笔记」移动Web开发之rem适配布局10 一.rem单位 1.1 rem 单位 二.媒体查询 2.1 什么是媒体查询 2.2 语法规范 2.2.1 mediatype 查询类型 2.2.2 关键 ...
- 「学习笔记」HTML5CSS3提高6(上)
「学习笔记」HTML5&CSS3提高6(上) HTML5新特性 概述 语义化标签 (★★) 多媒体标签 视频标签- video(★★★) 基本使用 兼容写法 video 常用属性 音频标签- ...
- 【学习笔记】多项式相关算法
[学习笔记]多项式相关算法 手动博客搬家: 本文发表于20181125 13:19:28, 原地址https://blog.csdn.net/suncongbo/article/details/844 ...
- 「学习笔记」品优购项目-上(页面公共部分 )
「学习笔记」品优购项目-上 品优购项目-上 目标 品优购项目规划 网站制作流程 品优购项目介绍 品优购项目的学习目的 开发工具以及技术栈 开发工具 技术栈 品优购项目搭建工作 创建的文件夹如下(称为项 ...
- 「学习笔记」ISAP求最大流
ISAP学习笔记 ISAP是OI中求最大流的常用方法之一.相对于Dinic,ISAP的速度提升了很多,但编码复杂度也上升了不少. 约定 采用邻接表存储图,对于每条弧,增加一条容量为0的逆向边. d数组 ...
- 「学习笔记」无标号生成树计数总结
感觉关于树/图计数是一门博大精深的学问,不知道这辈子有没有搞到足够明白的机会了啊QwQ 一.无标号有根树计数: 基本上是这篇的详细版本. 考虑令fnf_nfn表示n个点的无标号有根树数量,其生成函数 ...
最新文章
- 知识点回顾-简单的TableView单组数据展示/多组数据展示
- 最高补助1000万元!这类程序员2020年要过好日子了……
- 程序员最害怕的5件事,你中招了吗?
- springboot controller 分页查询_Spring Boot实战分页查询附近的人:Redis+GeoHash+Lua
- 【报错笔记】运行Maven项目时发现项目Build错误
- MySQL出现:ERROR 3 (HY000): Error writing file '/tmp/MYbEd05t' (Errcode: 28)
- android——wifi系统架构
- web 基本概念辨异 —— URI 与 URL
- aes解密设置utf8 php,PHP aes (ecb)解密后乱码问题
- cpu核心 线程 进程_科个普:进程、线程、并发、并行
- ASP.NET 2.0下实现匿名用户向注册用户的迁移(上) zhuan
- 网络编程必读经典书籍
- android wps页面设置,WPS中设置纸张的方法
- 我设计开发的第一个产品发布了,微信小程序“集美装修效果图“
- [行人重识别论文阅读]无监督学习发展与小结
- Python处理PDF——PyMuPDF的安装与使用(1)
- Elasticsearch(三) Python 使用 elasticsearch 的基本操作
- CISSP第6/8知识点错题集
- 深度学习图像分类:Kaggle植物幼苗分类(Plant Seedlings Classification)完整代码
- 去除em斜体的方法_鱼缸水体pH值对观赏鱼的影响,以及偏高或偏低的调节方法...
热门文章
- C++学习之路(六):实现一个String类
- MP4大文件虚拟HLS分片技术,避免服务器大量文件碎片
- Cesium学习笔记(五):3D 模型 (http://blog.csdn.net/umgsoil/article/details/74572877)
- ES6之let(理解闭包)和const命令
- Android 高仿新浪微博底部导航栏,实现双击首页Tab,页面的ListView滚动、刷新
- 23种设计模式整体详解
- 走向.NET架构设计—第四章—业务层分层架构(后篇)
- c++之趣味new代码大家看
- java基础-迭代器(Iterator)与增强for循环
- Adobe Flash Player 10新特性详解:支持GPU加速