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中所有权 ...
随机推荐
- 二、JavaScript基础(2)
BOM基础加强 1.浏览器对象BOM DOM Window DOM Navigator DOM Screen DOM History DOM Location 2.浏览器对象的使用 History H ...
- MySQL查看、创建和删除索引的方法
本文实例讲述了MySQL查看.创建和删除索引的方法.分享给大家供大家参考.具体如下: 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术,能够大大提高查询效率.特别 ...
- kernel中,dump_stack打印调用栈,print_hex_dump打印一片内存,记录一下
kernel中,dump_stack打印调用栈,print_hex_dump打印一片内存,记录一下
- linux-----jdk、activemq安装
功能 描述 JAVA_HOME安装路径 查找JAVA_HOME安装路径 echo $JAVA_HOME linux下安装activemq A:解压安装包 tar - zxvf apache-activ ...
- 【Python全栈-后端开发】Django入门基础-2
Django入门基础知识-2 一 .模版 一.模版的组成 HTML代码+逻辑控制代码 二.逻辑控制代码的组成 1 变量(使用双大括号来引用变量) {{var_name}} 2 标签(tag)的使用 ...
- darknet集成遇到的问题以及解决方法
将darknet集成进工程时,遇到了一些问题,下面记录一下解决方法: 集成步骤: 首先在yolo编译的时候,需要将三个开关打开: #define GPU#define CUDNN#define OPE ...
- Spring中IOC和AOP的详细解释(转)
原文链接:Spring中IOC和AOP的详细解释 我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂 ...
- Echarts-图表根据值的不同展示成不同的颜色
series : [ { name:'直接访问', type:'bar', barWidth: '60%', ...
- Ocelot:API网关概要
一.概要 Ocelot是.Net Core下一个开源API网关:Ocelot主要目标是在.NET在微服务或面向服务架构中提供统一的入口服务, Ocelot拿到HttpRequest对象到管道后,先创建 ...
- centos----------centos下安装谷歌浏览器
1.首先你已经安装了带有可视化界面的centos系统. 2.打开里面自带的一个浏览器,输入网址 http://chrome.richardlloyd.org.uk/install_chrome.sh ...