P5205 【模板】多项式开根
思路
按如下式子计算即可
\]
代码
// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int MAXN = 300000;
const int G = 3;
const int invG = 332748118;
const int MOD = 998244353;
int n;
struct Poly{
int t;//次数界
int data[MAXN];
Poly(){}
Poly(int x,int val[]){
for(int i=0;i<=x;i++)
data[i]=val[i];
}
};
int pow(int a,int b){
int ans=1;
while(b){
if(b&1)
ans=(1LL*ans*a)%MOD;
a=(1LL*a*a)%MOD;
b>>=1;
}
return ans;
}
void rever(Poly &a){
for(int i=0,j=a.t;i<j;i++,j--){
swap(a.data[i],a.data[j]);
}
}
void save(Poly &a,int top){
for(int i=top+1;i<=a.t;i++)
a.data[i]=0;
a.t=top;
}
void output(Poly a){
putchar('\n');
printf("a.times=%lld\n",a.t);
putchar('\n');
for(int i=0;i<=a.t;i++)
printf("%lld ",a.data[i]);
putchar('\n');
putchar('\n');
}
void NTT(Poly &a,int opt,int n){//1 DFT 0 IDFT
int lim=0;
while((1<<(lim))<n)
lim++;
n=(1<<lim);
for(int i=0;i<n;i++){
int t=0;
for(int j=0;j<lim;j++)
if((i>>j)&1)
t|=(1<<(lim-j-1));
if(i<t)
swap(a.data[i],a.data[t]);
}
for(int i=2;i<=n;i<<=1){
int len=i/2;
int tmp=pow((opt)?G:invG,(MOD-1)/i);
for(int j=0;j<n;j+=i){
int arr=1;
for(int k=j;k<j+len;k++){
int t=(1LL*a.data[k+len]*arr)%MOD;
a.data[k+len]=(a.data[k]-t+MOD)%MOD;
a.data[k]=(a.data[k]+t)%MOD;
arr=(1LL*arr*tmp)%MOD;
}
}
}
if(!opt){
int invN = pow(n,MOD-2);
for(int i=0;i<n;i++){
a.data[i]=(a.data[i]*invN)%MOD;
}
}
}
void mul(Poly &a,Poly b){//a=a*b
int num=(a.t+b.t),lim=0;
while((1<<(lim))<=((num+2)))
lim++;
lim=(1<<lim);
NTT(a,1,lim);
NTT(b,1,lim);
for(int i=0;i<lim;i++)
a.data[i]=(1LL*a.data[i]*b.data[i])%MOD;
NTT(a,0,lim);
a.t=num;
for(int i=num+1;i<lim;i++)
a.data[i]=0;
}
void Inv(Poly a,Poly &inv,int dep,int &len){//
if(dep==1){
inv.data[0]=pow(a.data[0],MOD-2);
inv.t=dep-1;
return;
}
Inv(a,inv,(dep+1)>>1,len);
static Poly tmp1,tmp2,tmp;
while((dep<<1)>len)
len<<=1;
for(int i=0;i<dep;i++)
tmp.data[i]=a.data[i];
for(int i=dep;i<len;i++)
tmp.data[i]=0;
NTT(tmp,1,len);
NTT(inv,1,len);
for(int i=0;i<len;i++)
inv.data[i]=1LL*inv.data[i]*((2-1LL*inv.data[i]*tmp.data[i])%MOD+MOD)%MOD;
NTT(inv,0,len);
for(int i=dep;i<len;i++)
inv.data[i]=0;
inv.t=dep-1;
}
void div(Poly a,Poly b,Poly &D,Poly &R){
static Poly tmp1,tmp2;
int Up=a.t-b.t+1,midlen=1;
tmp1=b;
rever(tmp1);
Inv(tmp1,tmp2,Up,midlen);
tmp1=a;
rever(tmp1);
mul(tmp2,tmp1);
save(tmp2,a.t-b.t);
rever(tmp2);
D=tmp2;
mul(tmp2,b);
for(int i=0;i<b.t;i++)
R.data[i]=(a.data[i]-tmp2.data[i]+MOD)%MOD;
R.t=b.t-1;
}
void sqrt(Poly a,Poly &b,int &midlen,int dep){
// printf("dep=%lld\n",dep);
if(dep==1){
b.data[0]=1;
b.t=dep-1;
return;
}
sqrt(a,b,midlen,(dep+1)>>1);
// printf("dep=%lld\n",dep);
while((dep<<1)>(midlen))
midlen<<=1;
static Poly tmp1,tmp2,tmp3;
tmp1=b;tmp3=b;
save(tmp1,dep-1);
save(tmp3,dep-1);
save(tmp2,-1);
int midlent=1;
for(int i=0;i<dep;i++)
tmp1.data[i]=(tmp1.data[i]*2)%MOD;
Inv(tmp1,tmp2,dep,midlent);
mul(b,tmp3);
for(int i=0;i<dep;i++)
b.data[i]=(b.data[i]+a.data[i])%MOD;
mul(b,tmp2);
for(int i=dep;i<midlen;i++)
b.data[i]=0;
b.t=dep-1;
// output(b);
}
Poly a,b;
signed main(){
scanf("%lld",&n);
for(int i=0;i<n;i++)
scanf("%lld",&a.data[i]);
a.t=n-1;
int midlen=1;
sqrt(a,b,midlen,n);
for(int i=0;i<=b.t;i++)
printf("%lld ",b.data[i]);
putchar('\n');
return 0;
}
P5205 【模板】多项式开根的更多相关文章
- P5277 【模板】多项式开根(加强版)(bsgs or Cipolla)
题面 传送门 题解 首先你得会多项式开根->这里 其次你得会解形如 \[x^2\equiv a \pmod{p}\] 的方程 这里有两种方法,一个是\(bsgs\)(这里),还有一种是\(Cip ...
- FFT模板 生成函数 原根 多项式求逆 多项式开根
FFT #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> ...
- CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)
传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多 ...
- Codeforces 250 E. The Child and Binary Tree [多项式开根 生成函数]
CF Round250 E. The Child and Binary Tree 题意:n种权值集合C, 求点权值和为1...m的二叉树的个数, 形态不同的二叉树不同. 也就是说:不带标号,孩子有序 ...
- 【XSY2730】Ball 多项式exp 多项式ln 多项式开根 常系数线性递推 DP
题目大意 一行有\(n\)个球,现在将这些球分成\(k\) 组,每组可以有一个球或相邻两个球.一个球只能在至多一个组中(可以不在任何组中).求对于\(1\leq k\leq m\)的所有\(k\)分别 ...
- 【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆
题目大意 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots ,c_n\).如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合\(\{c_1,c_2,\ldots ,c_n\ ...
- BZOJ3625 [Codeforces Round #250]小朋友和二叉树(生成函数+多项式开根)
设f(n)为权值为n的神犇二叉树个数.考虑如何递推求这个东西. 套路地枚举根节点的左右子树.则f(n)=Σf(i)f(n-i-cj),cj即根的权值.卷积的形式,cj也可以通过卷上一个多项式枚举.可以 ...
- 【BZOJ3625】【codeforces438E】小朋友和二叉树 生成函数+多项式求逆+多项式开根
首先,我们构造一个函数$G(x)$,若存在$k∈C$,则$[x^k]G(x)=1$. 不妨设$F(x)$为最终答案的生成函数,则$[x^n]F(x)$即为权值为$n$的神犇二叉树个数. 不难推导出,$ ...
- BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根
生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...
- [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)
[BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...
随机推荐
- less的安装与用法
1. node.js node.js是一个前端的框架 自带一个包管理工具npm node.js 的安装 官网:http://nodejs.cn/ 在命令行检验是否安装成功 打开cmd 切换到项目目录, ...
- PYTHON SOCKET编程简介
原文地址: PYTHON SOCKET编程详细介绍 Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 Soc ...
- socket与http
参考文档:http://blog.csdn.net/zeng622peng/article/details/5546384 1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可 ...
- PM2.5环境检测系统的设计与分析
PM2.5环境检测系统的设计与分析 摘要: 大气颗粒物污染对人类健康和生态环境造成了很大的影响,这让人们逐渐重视起对细颗粒物PM2.5检测技术的研究.本文阐述了PM2.5浓度检测的五种方法,在对上 ...
- Java编程基础篇第四章
循环结构 循环结构的分类 for循环,while循环,do...while()循环 for循环 注意事项: a:判断条件语句无论简单还是复杂结果是boolean类型 b:循环体语句如果是一条语句,大括 ...
- yum命令查看某个命令是由那个包提供的
[root@linux-node2 ~]$ yum whatprovides fuserLoaded plugins: fastestmirrorLoading mirror speeds from ...
- HDU 2612 - Find a way - [BFS]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2612 Problem DescriptionPass a year learning in Hangz ...
- Codeforces Round #539 div2
Codeforces Round #539 div2 abstract I 离散化三连 sort(pos.begin(), pos.end()); pos.erase(unique(pos.begin ...
- 使用docker容器运行MySQL数据库并持久化数据文件
1.下载mysql镜像 # docker pull mysql 2.启动mysql容器 # docker run -itd -v /data:/var/lib/mysql -p 33060:3306 ...
- LeetCode 520 Detect Capital 解题报告
题目要求 Given a word, you need to judge whether the usage of capitals in it is right or not. We define ...