Luogu 4726 【模板】多项式指数函数
补补补……
这个题的解法让我认识到了泰勒展开的美妙之处。
泰勒展开
泰勒展开就是用一个多项式型的函数去逼近一个难以准确描述的函数。
有公式
$$f(x)\approx g(x) = g(x_0) + \frac{g'(x_0)}{1!}(x - x_0) + \frac{g^{(2)}(x_0)}{2!}(x - x_0)^2 + \cdots + \frac{g^{(n)}(x_0)}{n!}(x - x_0)^n$$
在这里$g^{(n)}$表示$g$的$n$阶导。
在$0$这个点的泰勒展开$(x_0 = 0)$叫做麦克劳林级数,利用这个东西可以很精确地去逼近原来的函数。
比如,
$$f(x) = e^x \approx 1 + \frac{x}{1!} + \frac{x^2}{2!} + \frac{x^3}{3!} + \frac{x^4}{4!} + \cdots = \sum_{i = 0}^{\infty}\frac{x^i}{i!}$$
$$f(x) = ln(1 - x) \approx 0 - \frac{x}{1} - \frac{x^2}{2} - \frac{x^3}{3} - \cdots = -\sum_{i = 1}^{\infty}\frac{x^i}{i}$$
一些定义
有了泰勒展开之后我们可以定义一些看上去很难定义的东西,比如这个多项式取$ln$:
$$ln(1 - A(x)) = -\sum_{i = 1}^{\infty}\frac{A(x)^i}{i}$$
这也解释了为什么给出的多项式常数项一定是$1$。
同理,多项式$exp$的定义是这样子的:
$$exp(A(x)) = \sum_{i = 0}^{\infty}\frac{A(x)^i}{i!}$$
可以发现这样子定义之后就好理解很多了。
牛顿迭代
牛顿迭代是解决多项式问题的利器,可以一口气解决好多推式子问题。
牛顿法求解方程的近似解在高中课本里面有提到过,它也可以用来解决多项式的问题。
现在我们尝试用另一种手段得到它。
要求$G(F(x)) \equiv 0 (\mod x^n)$,通过题目给出的特定的$G(x)$,我们可以算出$F(x)$。
首先我们尝试解决常数项的问题,一般来说,这个问题都非常简单,比如本题中可以直接求出常数项为$1$。
现在假设已经求出了$F_0(x)$满足$G(F_0(x)) \equiv 0(\mod x^{\left \lceil \frac{n}{2} \right \rceil})$,我们尝试求$F(x)$满足$G(F(x)) \equiv 0 (\mod x^n)$。
可以对$G(x)$在$F_0(x)$处进行泰勒展开,得到
$$G(F(x)) = G(F_0(x)) + G'(F_0(x))(F(x) - F_0(x)) + G''(F_0(x))(F(x) - F_0(x))^2 + \cdots$$
这是在$(\mod x^n)$次意义下进行的,在多项式求逆的时候已经证明过了$(F(x) - F_0(x))^n$在$n \geq 2$的时候模$x^n$为$0$,后面就可以不用写下去了。
注意到$G(F(x)) \equiv 0 (\mod x^n)$,有
$$F(x) \equiv F_0(x) - \frac{G(F_0(x))}{G'(F_0(x))}(\mod x^n)$$
这个式子就是牛顿迭代的式子了。
鼓掌~~~
考虑一下在这个题中怎么取这个$G(x)$。
题目要求
$$B(x) \equiv e^{A(x)} (\mod x^n)$$
发现这个$e^x$并不是很方便,所以两边取一下$ln$,移项,
$$ln(B(x)) - A(x) \equiv 0 (\mod x^n)$$
那就记$G(F(x)) = lnF(x) - A(x)$。
因为$A(x)$和$F(x)$在这里等价于两个数,$F(x)$是自变量,所以$A(x)$就看成常数,在求导的时候可以直接消掉。
整理一下就得到了多项式$exp$的式子:
$$F(x) = F_0(x)(1 - lnF_0(x) + A(x))$$
左转去复制各种模板过来,于是就可以愉快地递归求解了!
时间复杂度仍然是$O(nlogn)$。
在吉老师博客里看到了关于这堆东西常数的吐槽,感觉妙不可言。
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = << ; int n;
ll f[N], g[N]; namespace Poly {
const int L = << ;
const ll P = 998244353LL; int lim, pos[L];
ll f[L], g[L], h[L], tmp[L]; inline ll fpow(ll x, ll y) {
ll res = ;
for (x %= P; y > ; y >>= ) {
if (y & ) res = res * x % P;
x = x * x % P;
}
return res;
} inline void prework(int len) {
int l = ;
for (lim = ; lim < len; lim <<= , ++l);
for (int i = ; i < lim; i++)
pos[i] = (pos[i >> ] >> ) | ((i & ) << (l - ));
} inline void ntt(ll *c, int opt) {
for (int i = ; i < lim; i++)
if (i < pos[i]) swap(c[i], c[pos[i]]);
for (int i = ; i < lim; i <<= ) {
ll wn = fpow(, (P - ) / (i << ));
if (opt == -) wn = fpow(wn, P - );
for (int len = i << , j = ; j < lim; j += len) {
ll w = ;
for (int k = ; k < i; k++, w = w * wn % P) {
ll x = c[j + k], y = w * c[j + k + i] % P;
c[j + k] = (x + y) % P, c[j + k + i] = (x - y + P) % P;
}
}
} if (opt == -) {
ll inv = fpow(lim, P - );
for (int i = ; i < lim; i++) c[i] = c[i] * inv % P;
}
} void inv(ll *a, ll *b, int len) {
if (len == ) {
b[] = fpow(a[], P - );
return;
} inv(a, b, (len + ) >> );
prework(len << );
for (int i = ; i < lim; i++) f[i] = g[i] = ;
for (int i = ; i < len; i++) f[i] = a[i], g[i] = b[i];
ntt(f, ), ntt(g, );
for (int i = ; i < lim; i++)
g[i] = g[i] * (2LL - g[i] * f[i] % P + P) % P;
ntt(g, -); for (int i = ; i < len; i++) b[i] = g[i];
} inline void direv(ll *c, int len) {
for (int i = ; i < len - ; i++) c[i] = c[i + ] * (i + ) % P;
c[len - ] = ;
} inline void integ(ll *c, int len) {
for (int i = len - ; i > ; i--) c[i] = c[i - ] * fpow(i, P - ) % P;
c[] = ;
} inline void ln(ll *a, ll *b, int len) {
for (int i = ; i < len; i++) h[i] = ;
inv(a, h, len); for (int i = ; i < len; i++) b[i] = a[i];
direv(b, len); prework(len << );
ntt(h, ), ntt(b, );
for (int i = ; i < lim; i++) b[i] = b[i] * h[i] % P;
ntt(b, -); integ(b, len);
// for (int i = 0; i < lim; i++) h[i] = 0;
} ll F[L], G[L];
void exp(ll *a, ll *b, int len) {
if (len == ) {
b[] = ;
return;
}
exp(a, b, (len + ) >> ); ln(b, F, len);
F[] = (a[] % P + - F[] + P) % P;
for (int i = ; i< len; i++) F[i] = (a[i] - F[i] + P) % P; prework(len << );
for (int i = len; i < lim; i++) F[i] = ;
for (int i = ; i < lim; i++) G[i] = ;
for (int i = ; i < len; i++) G[i] = b[i];
ntt(F, ), ntt(G, );
for (int i = ; i < lim; i++) F[i] = F[i] * G[i] % P;
ntt(F, -); for (int i = ; i < lim; i++) b[i] = F[i];
} }; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for (; ch > ''|| ch < ''; ch = getchar())
if (ch == '-') op = -;
for (; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} int main() {
read(n);
for (int i = ; i < n; i++) read(f[i]);
Poly :: exp(f, g, n);
for (int i = ; i < n; i++)
printf("%lld%c", g[i], " \n"[i == n - ]);
return ;
}
一点点推广
取不同的$G(x)$可以得到不同的结果,简单推导出答案的式子。
比如:
多项式求逆,
$$G(F(x)) = F(x)A(x) - 1$$
多项式开方,
$$G(F(x)) = F(x)^2 - A(x)$$
……
还有一些应该会在做题的时候补全。
Luogu 4726 【模板】多项式指数函数的更多相关文章
- [洛谷P4726]【模板】多项式指数函数
题目大意:给出$n-1$次多项式$A(x)$,求一个 $\bmod{x^n}$下的多项式$B(x)$,满足$B(x) \equiv e^{A(x)}$. 题解:(by Weng_weijie) 泰勒展 ...
- [luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...
- Luogu P2742 模板-二维凸包
Luogu P2742 模板-二维凸包 之前写的实在是太蠢了.于是重新写了一个. 用 \(Graham\) 算法求凸包. 注意两个向量 \(a\times b>0\) 的意义是 \(b\) 在 ...
- luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)
luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...
- luogu P4726 多项式指数函数(模板题FFT、多项式求逆、多项式对数函数)
手动博客搬家: 本文发表于20181127 08:39:42, 原地址https://blog.csdn.net/suncongbo/article/details/84559818 题目链接: ht ...
- luogu P4726 【模板】多项式指数函数 多项式 exp 牛顿迭代 泰勒展开
LINK:多项式 exp 做多项式的题 简直在嗑药. 前置只是 泰勒展开 这个东西用于 对于一个函数f(x) 我们不好得到 其在x处的取值. 所以另外设一个函数g(x) 来在x点处无限逼近f(x). ...
- 洛谷P4726 【模板】多项式指数函数(多项式exp)
题意 题目链接 Sol 多项式exp,直接套泰勒展开的公式 \(F(x) = e^{A(x)}\) 求个导\(F'(x) = A(x)\) 我们要求的就是\(G(f(x)) = lnF(x) - A( ...
- Luogu4726 【模板】多项式指数函数(NTT+多项式求逆)
https://www.cnblogs.com/HocRiser/p/8207295.html 安利! #include<iostream> #include<cstdio> ...
- P4726 【模板】多项式指数函数
思路 按照式子计算即可 \[ F(x)=F_0(x)(1-\ln F_0(x) +A(x)) \] 代码 // luogu-judger-enable-o2 #include <cstdio&g ...
随机推荐
- GOF23设计模式之责任链模式(chain of responsibility)
一.责任链模式概述 将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求. 如果能则处理,否则传递给链上的下一个对象去处理. 定义责任链 (1)通过链表 ...
- (转)win7+iis7.5+asp.net下 CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 解决方案
本文转载自:http://www.cnblogs.com/finesite/archive/2011/01/28/1946940.html 网上搜的解决方案但在我的环境下仍旧没有解决,我的方法如下: ...
- ALSA声卡07_分析调用过程_学习笔记
1.编译新的strace工具分析aplay和amixer应用程序对声卡的调用过程 (1)因为旧的strace工具不能识别不能识别alsa声卡驱动程序里面的ioctrl. (2)编译过程参考http:/ ...
- jaxp使用笔记
XML文件的解析技术有DOM和SAX方式,在Android中还有pull解析方式,这里不再讨论 DOM解析的方式和js中的DOM操作是一致的,DOM解析一次将文档加载入内存建立树型模型,但是如果XML ...
- 【洛谷】P3908 异或之和(异或)
题目描述 求1 \bigoplus 2 \bigoplus\cdots\bigoplus N1⨁2⨁⋯⨁N 的值. A \bigoplus BA⨁B 即AA , BB 按位异或. 输入输出格式 输入格 ...
- zabbix 报警方式之 邮件报警(4)
一.为什么要自定义邮件脚本报警? 灵活,方便.可以自定义过滤信息. 下面是使用不同方式的邮件报警,一个是利用sendEmail程序来发送报警邮件,第二个是利用python脚本来发送邮件. 二.send ...
- 用 Sqlmap 识别 WAF
命令: ┌─[root@sch01ar]─[~] └──╼ #sqlmap -u "http://www.sch01ar.com/" --identify-waf --batch ...
- [Z] 一些关于http服务器架构设计的资料
开始关注这块儿,先从最基础最简单的入手.这里放一些我看过的觉得可以收藏的资料,主要是网页或博客,经典书籍之类有时间再看吧: 风格之争:Coroutine模型 vs 非阻塞/异步IO(callback)
- MySQL多项模糊查询
最近有个需求,就是要根据搜索框里面的关键字,找到符合条件的数据. 如果是单个条件的话,其实就是一个普通的select语句. 但是需求是这个关键字,要在id,desc,step等多个字段模糊查找. 然后 ...
- leetcode495
public class Solution { public int FindPoisonedDuration(int[] timeSeries, int duration) { ) { ; } ) ...