luogu P4726 多项式指数函数(模板题FFT、多项式求逆、多项式对数函数)

手动博客搬家: 本文发表于20181127 08:39:42, 原地址https://blog.csdn.net/suncongbo/article/details/84559818

题目链接: https://www.luogu.org/problem/show?pid=4726

题意: 给定\(n\)次多项式\(A(x)\) 求多项式\(f(x)\)满足\(f(x)\equiv e^{A(x)} (\mod x^n)\)

题解

这个比对数函数复杂一些。。
前铺知识
泰勒展开
对于一个函数,我们可以用以下方式用它的高阶导数进行无穷逼近:\[f(x)=f(a)+f'(a)(x-a)+f''(a)\frac{(x-a)^2}{2!}+f'''(a)\frac{(x-a)^3}{3!}+...\]
牛顿迭代
已知要求的多项式\(f\)满足\(g(f(x))\equiv 0(\mod x^n)\) \(g\)已知,那么可以通过如下的方式倍增求解:
假设求出了原问题\(\mod x^n\)的答案\(f_0(x)\), 考虑转移到\(f(x) \mod x^{2n}\).
根据泰勒展开公式: \[0=g(f)=g(f_0)+g'(f_0)(f-f_0)+g''(f_0)\frac{(f-f_0)^2}{2!}+...\]
但是,由于一个显然的结论——\(f\equiv f_0(\mod x^n)\), 因此\((f-f_0)^2\equiv 0(\mod x^{2n})\), 因此公式里只需要计算前两项,后面的项都在\(\mod x^{2n}\)意义下为\(0\)!
即\(g(f_0)+g'(f_0)(f-f_0)=0\)
\(f=f_0-\frac{g(f_0)}{g'(f_0)}\)
如此即可求解。
(太神了啊太神了啊呜呜呜。。我大概永远也搞不出这么神奇的东西吧。。)

本题题解
根据牛顿迭代的法则,令\(g(f)=\ln f-A\), 则\(f=f_0-\frac{\ln f_0-A}{\frac{1}{f_0}}=f_0(1-\ln f_0+A)\)
递归求解即可。
值得注意的是FFT的大小
\(A\)应该带入\(2n\)次, \(\ln f_0\)应该带入\(2n\)次, \(f_0\)应该带入\(n\)次, FFT乘法因为是\(2n\)次乘以\(n\)次,所以应该取到\(4n\)个单位根。
FFT这个地方太容易出错了!范围大了常数大好几倍,范围小了就会出错。
时间复杂度为\(T(n)=T(\frac{n}{2})+O(n\log n)\), \(T(n)=O(n\log n)\)
常数我算的应该是\(48\)倍。每次\(n\)到\(2n\)的迭代需要做一次\(2n\)的\(\ln\)和三次\(4n\)的DFT/IDFT. 因此\(18(2n\log n)+3(4n\log n)=48n\log n\).
(飞了……)

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define llong long long
#define ldouble long double
#define uint unsigned int
#define ullong unsigned long long
#define udouble unsigned double
#define uldouble unsigned long double
#define modinc(x) {if(x>=P) x-=P;}
#define pii pair<int,int>
#define piii pair<pair<int,int>,int>
#define piiii pair<pair<int,int>,pair<int,int> >
#define pli pair<llong,int>
#define pll pair<llong,llong>
#define Memset(a,x) {memset(a,x,sizeof(a));}
using namespace std;const int N = 1<<19;
const int LGN = 19;
const int G = 3;
const int P = 998244353;
llong tmp1[N+3],tmp2[N+3],tmp3[N+3],tmp4[N+3]; //inv
llong tmp5[N+3],tmp6[N+3],tmp7[N+3],tmp8[N+3]; //ln
llong tmp9[N+3],tmp10[N+3],tmp11[N+3],tmp12[N+3]; //exp
llong a[N+3],b[N+3];
int id[N+3];
int n;llong quickpow(llong x,llong y)
{llong cur = x,ret = 1ll;for(int i=0; y; i++){if(y&(1ll<<i)){ret = ret*cur%P;y-=(1ll<<i);}cur = cur*cur%P;}return ret;
}
llong mulinv(llong x) {return quickpow(x,P-2);}void initid(int dgr)
{int len = 0;for(int i=0; i<=LGN; i++) if(dgr==(1<<i)) {len = i; break;}id[0] = 0;for(int i=1; i<dgr; i++) id[i] = (id[i>>1]>>1)|((i&1)<<(len-1));
}void ntt(int dgr,int coe,llong poly[],llong ret[])
{initid(dgr);for(int i=0; i<dgr; i++) ret[i] = poly[i];for(int i=0; i<dgr; i++) if(i<id[i]) swap(ret[i],ret[id[i]]);for(int i=1; i<=(dgr>>1); i<<=1){llong tmp = quickpow(G,(P-1)/(i<<1));if(coe==-1) tmp = mulinv(tmp);for(int j=0; j<dgr; j+=(i<<1)){llong expn = 1ll;for(int k=0; k<i; k++){llong x = ret[j+k],y = ret[j+k+i]*expn%P;ret[j+k] = x+y; modinc(ret[j+k]);ret[j+i+k] = x-y+P; modinc(ret[j+i+k]);expn = (expn*tmp)%P;}}}if(coe==-1){llong tmp = mulinv(dgr);for(int j=0; j<dgr; j++) ret[j] = ret[j]*tmp%P;}
}void polyinv(int dgr,llong poly[],llong ret[])
{for(int i=0; i<dgr; i++) ret[i] = 0ll;ret[0] = mulinv(poly[0]);for(int i=1; i<=(dgr>>1); i<<=1){for(int j=0; j<(i<<2); j++) tmp1[j] = j<i ? ret[j] : 0ll;for(int j=0; j<(i<<2); j++) tmp2[j] = j<(i<<1) ? poly[j] : 0ll;ntt((i<<2),1,tmp1,tmp3); ntt((i<<2),1,tmp2,tmp4);for(int j=0; j<(i<<2); j++) tmp3[j] = tmp3[j]*tmp3[j]%P*tmp4[j]%P;ntt((i<<2),-1,tmp3,tmp4);for(int j=0; j<(i<<1); j++) ret[j] = (tmp1[j]+tmp1[j]-tmp4[j]+P)%P;}for(int i=dgr; i<(dgr<<1); i++) ret[i] = 0ll;
}void polyder(int dgr,llong poly[],llong ret[])
{for(int i=0; i<dgr-1; i++) ret[i] = poly[i+1]*(i+1)%P;
}void polyint(int dgr,llong poly[],llong ret[])
{for(int i=1; i<dgr; i++) ret[i] = poly[i-1]*mulinv(i)%P;
}void polyln(int dgr,llong poly[],llong ret[])
{for(int i=0; i<dgr; i++) ret[i] = 0ll;polyder(dgr,poly,tmp5);polyinv(dgr,poly,tmp6);ntt((dgr<<1),1,tmp5,tmp7); ntt((dgr<<1),1,tmp6,tmp8);for(int i=0; i<(dgr<<1); i++) tmp7[i] = tmp7[i]*tmp8[i]%P;ntt((dgr<<1),-1,tmp7,tmp8);polyint(dgr,tmp8,ret);
}void polyexp(int dgr,llong poly[],llong ret[])
{for(int i=0; i<dgr; i++) ret[i] = i==0;for(int i=1; i<=(dgr>>1); i<<=1){for(int j=0; j<(i<<2); j++) tmp9[j] = j>=(i<<1) ? 0ll : ((j==0)+poly[j])%P;for(int j=0; j<(i<<2); j++) tmp10[j] = j>=i ? 0ll : ret[j];polyln((i<<1),tmp10,tmp11);for(int j=0; j<(i<<1); j++) {tmp9[j] = tmp9[j]-tmp11[j]+P; modinc(tmp9[j]);}ntt((i<<2),1,tmp10,tmp12); ntt((i<<2),1,tmp9,tmp11);for(int j=0; j<(i<<2); j++) tmp12[j] = tmp12[j]*tmp11[j]%P;ntt((i<<2),-1,tmp12,tmp11);for(int j=0; j<(i<<1); j++) ret[j] = tmp11[j];}
}int main()
{scanf("%d",&n); int dgr = 1; while(dgr<=n) dgr<<=1;for(int i=0; i<n; i++) scanf("%lld",&a[i]);polyexp(dgr,a,b);for(int i=0; i<n; i++) printf("%lld ",b[i]);return 0;
}

发表于 2019-01-23 20:22 suncongbo 阅读(...) 评论(...) 编辑 收藏

刷新评论刷新页面返回顶部

luogu P4726 多项式指数函数(模板题FFT、多项式求逆、多项式对数函数)相关推荐

  1. luogu P4512 多项式除法 (模板题、FFT、多项式求逆)

    luogu P4512 多项式除法 (模板题.FFT.多项式求逆) 手动博客搬家: 本文发表于20181206 14:42:53, 原地址https://blog.csdn.net/suncongbo ...

  2. CF438E The Child and Binary Tree(有意思的生成函数 + 多项式求逆 + 多项式开方)

    整理的算法模板合集: ACM模板 点我看多项式全家桶(●^◡_◡◡​^●) CF438E The Child and Binary Tree 简单的黑题 首先我们发现模数为99824435399824 ...

  3. P6295-有标号 DAG 计数【多项式求逆,多项式ln】

    正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有nnn个点的弱联通DAGDAGDAG数量. 1≤n≤1051\leq n\leq 10^5 ...

  4. 多项式牛顿迭代(应用:求逆,开根,对数exp)

    多项式牛顿迭代 给定多项式g(x)g(x)g(x),求f(x)f(x)f(x),满足g(f(x))≡0(modxn)g(f(x)) \equiv 0 \pmod {x ^ n}g(f(x))≡0(mo ...

  5. [COGS2189][HZOI 2015]帕秋莉的超级多项式-NTT-多项式求逆-多项式求ln-多项式开方-多项式求exp-多项式快速幂

    帕秋莉的超级多项式 [题目描述] 在幻想乡,帕秋莉·诺蕾姬(パチュリー·ノーレッジ)是以宅在图书馆闻名的魔法使. 其语文,数学,英语,物理,化学,生物,政治,历史,地理,哲♂学,无所不通晓. 今天,她 ...

  6. 模板——树状数组求逆序对

    题目链接:https://www.luogu.org/problemnew/show/P1908 1 #include <map> 2 #include <set> 3 #in ...

  7. 多项式算法5:多项式求逆

    多项式算法5:多项式求逆 多项式求逆 前置知识: FFT NTT 多项式求逆 这里的多项式求逆,其实是求多项式的逆元. 对于多项式A(x)A(x)A(x),如果存在A(x)B(x)≡1(modxn)A ...

  8. 多项式的求逆、取模和多点求值学习小记

    最近学习了多项式的求逆.取模和多点求值,这些方法能够解决很多多项式问题. 这三个操作是环环相扣的,很有趣,学完后不妨记录一下. 多项式求逆 给出一个次数界为 nnn 的多项式 A(x)A(x)A(x) ...

  9. 多项式求逆与多项式除法/取模

    多项式求逆 Procedure 多项式求逆是多项式模块中的一个重要操作("操作"这个词看出如今多项式题是多么的工业化,犹如毒瘤8操作LCT),在做生成函数/多项式除法.多项式取模/ ...

最新文章

  1. linux vi 撤销重做于前进后退--转
  2. php 文档转html格式文件,php学习笔记之将word文档转化为HTML文件
  3. u-boot向linux内核传递启动参数
  4. 最大值和最小值的差(信息学奥赛一本通-T1112)
  5. 数字图像识别笔记(第三章-灰度变换与空间滤波)
  6. 魔方——操作阶数实验
  7. 从数组中删除最后一项
  8. HanLP里使用DAT存取字典的方法
  9. 谷歌(Chrom)浏览器遇到同步已暂停的解决办法
  10. 流式布局使用鸿洋大神写的库:com.hyman:flowlayout-lib:1.1.2
  11. 【GPT-4】立即停止训练比 GPT-4 更强的模型,至少六个月!马斯克、图灵奖得主等数千 AI 专家紧急呼吁
  12. error: device unauthorized.This adb server's $ADB_VENDOR_KEYS is not set
  13. DataBase_数据库的行式存储与列式存储
  14. linux 中的.so和.a文件
  15. 图论宽度优先搜索---八数码
  16. 0715今日歌单 One Last Kiss, 耗尽
  17. 威盛卖掉威睿电通CDMA技术:Intel也全网通了!
  18. 计算机软件设计专业的英语翻译,关于计算机专业java app设计的毕业设计论文英文英语外文文献翻译成品资料:Java应用程序的高效运行时方面编织(中英文双语对照)(35页)-原创力文档...
  19. 修改数据表字段类型与字段名字
  20. 详解RAM、ROM、FLASH的区别

热门文章

  1. MatConvnet工具箱文档翻译理解(1)
  2. [Medical Image Process] 3.4 Morphology Application—Watershed Algorithm 分水岭算法
  3. vs2010 失效后的解决办法
  4. 快速融入新团队的一点个人体会
  5. python课堂笔记
  6. 调用函数,求1!+2!+3!+......+10!
  7. 链表之CIRCLEQ
  8. 二维数组中的查找---剑指Offer
  9. Android开发 Intent传递参数,获取数据为null
  10. c语言如何发现错误在哪里,二个C语言例子,编译没通过.不知道错在哪里[求助]