以NTT为运算基础,即默认支持在$o(n\log n)$的时间内多项式乘法

二次剩余:称$n$为模$p$意义下的二次剩余,当且仅当存在$x$使得$x^{2}\equiv n(mod\ p)$

当$p$为素数时,$n$为二次剩余当且仅当$p\mid n$或$n^{\frac{p-1}{2}}\equiv 1(mod\ p)$,且$[1,p)$中恰有$\frac{p-1}{2}$个数为二次剩余

模意义下开根号:当$p$为素数且$n$为模$p$意义下的二次剩余,求$x$使得$x^{2}\equiv n(mod\ p)$

当$p\mid n$,令$x=0$即可,否则即$n^{\frac{p-1}{2}}\equiv 1(mod\ p)$时

随机$a$使得$a^{2}-n$为非二次剩余,根据前面的结论,单次判定为$o(\log p)$,且随机次数为期望$o(1)$

令$w^{2}\equiv a^{2}-n(mod\ p)$(其中$w$类似于虚数单位$i$,并不存在),即有$w^{p-1}\equiv -1(mod\ p)$

将之化简,即$n\equiv (a-w)(a+w)(mod\ p)$,将$a\equiv a^{p}(mod\ p)$且$w\equiv -w^{p}(mod\ p)$,代入$a-w$中即可得到$n\equiv (a^{p}+w^{p})(a+w)(mod\ p)$

进一步的,不难得到$(a+w)^{p}\equiv a^{p}+w^{p}(mod\ p)$,那么$n\equiv (a+w)^{p+1}(mod\ p)$,将其开根号也即有$x\equiv (a+w)^{\frac{p+1}{2}}(mod\ p)$

在快速幂过程中,将每一个数用形如$a+bw$的形式描述(利用$w^{2}\equiv a^{2}-n$来消除高次项),且可以证明最终$b\equiv 0(mod\ p)$

牛顿迭代:给定函数$G$,若$G(F_{0})\equiv 0(mod\ x^{\frac{n}{2}})$,求$G(F)\equiv 0(mod\ x^{n})$,做法如下——

根据泰勒展开,有
$$
G(F)=\sum_{i=0}^{\infty}\frac{1}{i!}(F-F_{0})^{i}G^{(i)}(F_{0})\equiv 0(mod\ x^{n})
$$
(其中$G^{(i)}$指$G$的$i$阶导数)

若$G(F)$中若修改$F$的$i$次项系数,不影响$G(F)$中比$i$次数低的项系数,即有$F\equiv F_{0}(mod\ x^{\frac{n}{2}})$

进而,即$(F-F_{0})^{2}\equiv 0(mod\ x^{n})$,因此上式等价于$G(F_{0})+(F-F_{0})G'(F_{0})\equiv 0(mod\ x^{n})$

化简后,即$F\equiv F_{0}-\frac{G(F_{0})}{G'(F_{0})}(mod\ x^{n})$,再根据具体的$G$计算即可

多项式求逆:给定多项式$A$,求多项式$F$使得$AF\equiv 1(mod\ x^{n})$

将之简单化简,也即解$G(F)=F^{-1}-A\equiv 0(mod\ x^{n})$

(这里$G$需要保证$A$为单独一项,否则会导致嵌套)

$G(F)\equiv 0(mod\ x)$直接对常数项求逆元即可,接下来根据$F\equiv F_{0}-\frac{G(F_{0})}{G'(F_{0})}(mod\ x^{n})$,代入并化简即可得到$F\equiv (2-AF_{0})F_{0}(mod\ x^{n})$,直接NTT计算即可

由于每一层计算复杂度为$o(n\log n)$,总复杂度也为$o(n\log n)$

多项式除法:给定多项式$A$和$B$,求多项式$F$使得$AF\equiv B(mod\ x^{n})$

先利用多项式求逆找到$AF'\equiv 1(mod\ x^{n})$,令$F\equiv F'B(mod\ x^{n})$显然成立

多项式开方:给定多项式$A$,求多项式$F$使得$F^{2}\equiv A(mod\ x^{n})$

将之简单化简,也即解$G(F)=F^{2}-A\equiv 0(mod\ x^{n})$

$G(F)\equiv 0(mod\ x)$直接对常数项开根即可,接下来根据$F\equiv F_{0}-\frac{G(F_{0})}{G'(F_{0})}(mod\ x^{n})$,代入并化简即可得到$F\equiv \frac{F_{0}^{2}-A}{2F_{0}}(mod\ x^{n})$,利用多项式除法计算即可

由于每一层计算复杂度为$o(n\log n)$,总复杂度也为$o(n\log n)$

多项式求对数:给定多项式$A$,求多项式$F$使得$e^{F}\equiv A(mod\ x^{n})$

(关于这个$e^{F}$,将其对$F_{0}=0$这个多项式泰勒展开,即有$e^{F}=\sum_{i=0}^{\infty}\frac{1}{i!}F^{i}$)

如果使用与之前做法相同的思路,会导致其需要在过程中求多项式的exp,而求exp时又需要求对数,会导致嵌套而无法实现

事实上,对于多项式求对数,有更为简单(不依赖于exp)的做法——

对原式两边求导,即$F'e^{F}\equiv A(mod\ x^{n})$

代入$e^{F}\equiv A(mod\ x^{n})$,即$F'\equiv \frac{A}{A'}(mod\ x^{n})$

再对两边同时积分,即$F\equiv \int \frac{A}{A'}(mod\ x^{n})$

利用多项式求逆以及多项式积分法则,即可做到$o(n\log n)$的复杂度

多项式求exp:给定多项式$A$,求$F\equiv e^{A}(mod\ x^{n})$

将之简单化简,也即解$G(F)=\ln F-A\equiv 0(mod\ x^{n})$

由于$\ln F$的常数项一定为0,因此$A$的常数项也必然为0

$G(F)\equiv 0(mod\ x)$直接取$F=1$即可($A$常数项为0),接下来根据$F\equiv F_{0}-\frac{G(F_{0})}{G'(F_{0})}(mod\ x^{n})$,代入并化简即可得到$F\equiv (A-\ln F_{0}+1)F_{0}(mod\ x^{n})$,利用多项式求对数计算即可

由于每一层计算复杂度为$o(n\log n)$,总复杂度也为$o(n\log n)$

多项式求幂:给定多项式$A$,求$F\equiv A^{k}(mod\ x^{n})$

直接快速幂复杂度为$o(n\log^{2}n)$,并不足够优秀

对原式的两边同时取对数,即$\ln F\equiv k\ln A(mod\ x^{n})$,再同时exp即$F=e^{k\ln A}$,利用多项式求对数和exp即可$o(n\log n)$计算

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define mod 998244353
4 int n,k,tmp;
5 struct num{
6 int x,y;
7 num(int a,int b){
8 x=a,y=b;
9 }
10 num operator + (const num &k)const{
11 return num((x+k.x)%mod,(y+k.y)%mod);
12 }
13 num operator * (const num &k)const{
14 return num((1LL*x*k.x+1LL*y*k.y%mod*tmp)%mod,(1LL*x*k.y+1LL*k.x*y)%mod);
15 }
16 };
17 struct poly{
18 vector<int>a;
19 poly(){
20 a.clear();
21 }
22 poly(int x){
23 a.clear();
24 a.push_back(x);
25 }
26 }a,ans;
27 int qpow(int n,int m){
28 int s=n,ans=1;
29 while (m){
30 if (m&1)ans=1LL*ans*s%mod;
31 s=1LL*s*s%mod;
32 m>>=1;
33 }
34 return ans;
35 }
36 num qpow(num n,int m){
37 num s=n,ans=num(1,0);
38 while (m){
39 if (m&1)ans=ans*s;
40 s=s*s;
41 m>>=1;
42 }
43 return ans;
44 }
45 int Sqrt(int k){
46 int a;
47 while (1){
48 int x=1LL*rand()*rand()%mod,p=(1LL*x*x+mod-k)%mod;
49 if ((p)&&(qpow(p,(mod-1)/2)!=1)){
50 a=x;
51 break;
52 }
53 }
54 tmp=(1LL*a*a+mod-k)%mod;
55 int ans=qpow(num(a,1),(mod+1)/2).x;
56 return min(ans,mod-ans);
57 }
58 poly Add(poly a,int l){
59 while (a.a.size()<(1<<l))a.a.push_back(0);
60 return a;
61 }
62 poly Int(poly a,int n){
63 for(int i=(1<<n)-1;i;i--)a.a[i]=1LL*a.a[i-1]*qpow(i,mod-2)%mod;
64 a.a[0]=0;
65 return a;
66 }
67 poly derive(poly a,int n){
68 for(int i=1;i<(1<<n);i++)a.a[i-1]=1LL*a.a[i]*i%mod;
69 a.a[(1<<n)-1]=0;
70 return a;
71 }
72 void ntt(poly &a,int n,int p){
73 for(int i=0;i<(1<<n);i++){
74 int s=0;
75 for(int j=0;j<n;j++)
76 if (i&(1<<j))s+=(1<<n-j-1);
77 if (i<s)swap(a.a[i],a.a[s]);
78 }
79 for(int i=2;i<=(1<<n);i*=2){
80 int s=qpow(3,(mod-1)/i);
81 if (p)s=qpow(s,mod-2);
82 for(int j=0;j<(1<<n);j+=i){
83 for(int k=0,ss=1;k<(i>>1);k++,ss=1LL*ss*s%mod){
84 int x=a.a[j+k],y=1LL*a.a[j+k+(i>>1)]*ss%mod;
85 a.a[j+k]=(x+y)%mod;
86 a.a[j+k+(i>>1)]=(x+mod-y)%mod;
87 }
88 }
89 }
90 if (p){
91 int s=qpow((1<<n),mod-2);
92 for(int i=0;i<(1<<n);i++)a.a[i]=1LL*a.a[i]*s%mod;
93 }
94 }
95 poly add(poly a,poly b,int n){
96 for(int i=0;i<(1<<n);i++)a.a[i]=(a.a[i]+b.a[i])%mod;
97 return a;
98 }
99 poly mul(poly a,int k,int n){
100 for(int i=0;i<(1<<n);i++)a.a[i]=1LL*a.a[i]*k%mod;
101 return a;
102 }
103 poly mul(poly a,poly b,int n){
104 a=Add(a,n+1),b=Add(b,n+1);
105 for(int i=(1<<n);i<(1<<n+1);i++)a.a[i]=b.a[i]=0;
106 ntt(a,n+1,0);
107 ntt(b,n+1,0);
108 poly ans;
109 for(int i=0;i<(1<<n+1);i++)ans.a.push_back(1LL*a.a[i]*b.a[i]%mod);
110 ntt(ans,n+1,1);
111 for(int i=0;i<(1<<n);i++)ans.a.pop_back();
112 return ans;
113 }
114 poly inv(poly a,int n){
115 if (!n)return poly(qpow(a.a[0],mod-2));
116 poly s=Add(inv(a,n-1),n),ans=mul(a,s,n);
117 ans=add(mul(ans,mod-1,n),Add(poly(2),n),n);
118 return mul(ans,s,n);
119 }
120 poly sqrt(poly a,int n){
121 if (!n)return poly(Sqrt(a.a[0]));
122 poly s=Add(sqrt(a,n-1),n),ans=mul(s,s,n);
123 ans=mul(add(ans,a,n),(mod+1)/2,n);
124 return mul(ans,inv(s,n),n);
125 }
126 poly ln(poly a,int n){
127 return Int(mul(derive(a,n),inv(a,n),n),n);
128 }
129 poly exp(poly a,int n){
130 if (!n)return poly(1);
131 poly s=Add(exp(a,n-1),n),ans=ln(s,n);
132 ans=add(add(a,mul(ans,mod-1,n),n),Add(poly(1),n),n);
133 return mul(ans,s,n);
134 }
135 poly qpow(poly a,int n,int m){
136 return exp(mul(ln(a,n),m,n),n);
137 }
138 int main(){
139 srand(time(0));
140 scanf("%d%d",&n,&k);
141 a=Add(a,17);
142 for(int i=0;i<=n;i++)scanf("%d",&a.a[i]);
143 ans=exp(Int(inv(sqrt(a,17),17),17),17);
144 ans=add(mul(ans,mod-1,17),add(a,Add(poly(mod+2-a.a[0]),17),17),17);
145 ans=derive(qpow(add(ln(ans,17),Add(poly(1),17),17),17,k),17);
146 for(int i=0;i<n;i++)printf("%d ",ans.a[i]);
147 }

[loj150]挑战多项式的更多相关文章

  1. 【LOJ】#150. 挑战多项式

    原题链接 多项式全家桶!快乐!(好像少个除法,不过有除法好像不太快乐) (说真的这是我第一次写exp和开根...水平不行.. 从最基础要实现的操作开始吧.. 多项式取模\(x^n\) 这个..很简单了 ...

  2. Solution -「LOJ #150」挑战多项式 ||「模板」多项式全家桶

    \(\mathcal{Description}\)   Link.   给定 \(n\) 次多项式 \(F(x)\),在模 \(998244353\) 意义下求 \[G(x)\equiv\left\{ ...

  3. 【BZOJ4405】【WC2016】挑战NPC(带花树)

    [BZOJ4405][WC2016]挑战NPC(带花树) 题面 BZOJ 洛谷 Uoj Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个 ...

  4. 2016第七季极客大挑战Writeup

    第一次接触CTF,只会做杂项和一点点Web题--因为时间比较仓促,写的比较简略.以后再写下工具使用什么的. 纯新手,啥都不会.处于瑟瑟发抖的状态. 一.MISC 1.签到题 直接填入题目所给的SYC{ ...

  5. ThoughtWorks代码挑战——FizzBuzzWhizz

    很久没发表过文章了,今天看到一篇文章 最难面试的IT公司之ThoughtWorks代码挑战——FizzBuzzWhizz游戏(C#解法) 看到LZ的2B青年代码,实在是惨不忍睹,故写篇文章来探讨下这类 ...

  6. 小白挑战:AsyncTask源码分析

    //AsyncTask从本质上讲,是对ThreadPool和handler的封装. 在学习线程池相关的知识时,看到书中提到AsyncTask的实现中使用到了ThreadPool,于是把源码翻了出来, ...

  7. codevs 2924 数独挑战

    2924 数独挑战 http://codevs.cn/problem/2924/ 题目描述 Description "芬兰数学家因卡拉,花费3个月时间设计出了世界上迄今难度最大的数独游戏,而 ...

  8. 《征服 C 指针》笔记6:练习——挑战那些复杂的声明

    应该是小试牛刀的时候了. 在 ANSI C 的标准库中,有一个 atexit()函数.如果使用这个函数,当程序正常结束的时候,可以回调一个指定的函数. atexit()的原型定义如下: int ate ...

  9. NOIP2009多项式输出(水)【A004】

    [A004]潜伏者[难度A]—————————————————————————————————————————————————————————————————————————— [题目要求] 一元 n ...

随机推荐

  1. docker-compose 搭建kafka集群

    docker-compose搭建kafka集群 下载镜像 1.wurstmeister/zookeeper 2.wurstmeister/kafka 3.sheepkiller/kafka-manag ...

  2. 题解「雅礼集训 2017 Day7」事情的相似度

    题目传送门 Description 给出一个长度为 \(n\) 的 \(01\) 串为 \(s\),设 \(t_i\) 为 \(s_{1,2,..,i}\),有 \(m\) 次查询,每次查询给出 \( ...

  3. MySQL中如何选择合适的备份策略和备份工具

    ​数据库备份的重要性毋庸置疑,可以说,它是数据安全的最后一道防线.鉴于此,对于备份,我们通常会做以下要求: 多地部署 对于核心数据库,我们通常有两地三中心的部署要求.对于备份来说,也是如此. 一个备份 ...

  4. Bert文本分类实践(三):处理样本不均衡和提升模型鲁棒性trick

    目录 写在前面 缓解样本不均衡 模型层面解决样本不均衡 Focal Loss pytorch代码实现 数据层面解决样本不均衡 提升模型鲁棒性 对抗训练 对抗训练pytorch代码实现 知识蒸馏 防止模 ...

  5. python T1119紧急措施

    2021-10-18 题目: 近日,一些热门网站遭受黑客入侵,这些网站的账号.密码及 email 的数据惨遭泄露.你在这些网站上注册若干账号(使用的用户名不一定相同),但是注册时使用了相同的 emai ...

  6. Stream中的Collector收集器原理

    前言 Stream的基本操作因为平时工作中用得非常多(也能看到一些同事把Stream操作写得很丑陋),所以基本用法就不写文章记录了. 之所以能把Stream的操作写得很丑陋,完全是因为Stream底层 ...

  7. Hadoop MapReduce 保姆级吐血宝典,学习与面试必读此文!

    Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了关于 Hadoop 的官网及其他众多资料整理而成,为了整洁的排版及舒适的阅读,对于模糊不清晰的图片及黑白图片进行重新绘制成了高清彩图 ...

  8. Manjaro / ArchLinux 安装网易云音乐解决搜索不能输入中文方法

    0. 安装网易云音乐 yay -S netease-cloud-music 1.先安装qcef这个软件包. sudo yay -S qcef 2.编辑/opt/netease/netease-clou ...

  9. OO第三单元——JML规格化设计

    OO第三单元--JML规格化设计 JML语言的理论基础以及应用工具链情况 理论基础 JML是对JAVA程序进行规格化设计的一种表示语言,是一种行为接口规格语言.JML整合了Java和JAVAdoc,并 ...

  10. Prometheus重新标记

    Prometheus重新标记 一.背景 二.简化的指标抓取的生命周期 1.配置参数详解 1.`action:`存在的值 1.替换标签值 2.删除指标 3.创建或删除标签 2.删除标签注意事项 3.几个 ...