CF 438 E & bzoj 3625 小朋友和二叉树 —— 多项式开方
题目:http://codeforces.com/contest/438/problem/E
https://www.lydsy.com/JudgeOnline/problem.php?id=3625
多项式开方...
注意传进 sqt 中的模数应该是2的整数次幂,所以先补到 >=m ;
还要注意每次一定要先递归或进入别的子函数,再算 rev 数组,否则会被覆盖!
最重要的是 lim < n+n 而不是 <= ,否则会把数组撑大一倍(于是 (1<<18) 会RE),而如果真的把数组开到 (1<<19),又会因为进行 NTT 的长度变成两倍而(在bzoj上) TLE ...
想想,因为一开始已经是 lim <= m,所以 lim 一定是偏大的,也就是传进去的 n 并不是顶到的上界,也就不用必须 <= ;
而传进去的 n 本身是一个2的整数次幂,所以 <= 会纯粹的增大一倍;(所以直接写成 n>>1 就好了)
注意细节啊...
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=(<<)+,mod=,g=;
int n,m,c[xn],t[xn],tt[xn],rev[xn],sc[xn],inv2,f[xn];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
ll pw(ll a,int b)
{
ll ret=;
for(;b;b>>=,a=(a*a)%mod)if(b&)ret=(ret*a)%mod;
return ret;
}
int upt(int x){while(x>=mod)x-=mod; while(x<)x+=mod; return x;}
void ntt(int *a,int tp,int lim)
{
for(int i=;i<lim;i++)
if(i<rev[i])swap(a[i],a[rev[i]]);
for(int mid=;mid<lim;mid<<=)
{
int wn=pw(g,(mod-)/(mid<<));
if(tp==-)wn=pw(wn,mod-);
for(int j=,len=(mid<<);j<lim;j+=len)
{
int w=;
for(int k=;k<mid;k++,w=(ll)w*wn%mod)
{
int x=a[j+k],y=(ll)w*a[j+mid+k]%mod;
a[j+k]=upt(x+y); a[j+mid+k]=upt(x-y);
}
}
}
if(tp==)return; int inv=pw(lim,mod-);
for(int i=;i<lim;i++)a[i]=(ll)a[i]*inv%mod;
}
void inv(int *a,int *b,int n)
{
if(n==){b[]=pw(a[],mod-); return;}
inv(a,b,n>>);
int lim=,l=;
while(lim<n+n)lim<<=,l++;//<= (1<<19) TLE
for(int i=;i<lim;i++)rev[i]=((rev[i>>]>>)|((i&)<<(l-)));//after inv!!!
for(int i=;i<n;i++)tt[i]=a[i];
for(int i=n;i<lim;i++)tt[i]=;
ntt(tt,,lim); ntt(b,,lim);
for(int i=;i<lim;i++)b[i]=upt(((ll)-(ll)tt[i]*b[i])%mod*b[i]%mod);
ntt(b,-,lim);
for(int i=n;i<lim;i++)b[i]=;
}
void sqt(int *a,int *b,int n)
{
if(n==){b[]=; return;}
sqt(a,b,n>>);
int lim=,l=;
while(lim<n+n)lim<<=,l++;//<= (1<<19) TLE
for(int i=;i<lim;i++)t[i]=;
inv(b,t,n);
for(int i=;i<lim;i++)rev[i]=((rev[i>>]>>)|((i&)<<(l-)));//after inv!!!
for(int i=;i<n;i++)tt[i]=a[i];
for(int i=n;i<lim;i++)tt[i]=;
ntt(b,,lim); ntt(tt,,lim); ntt(t,,lim);
for(int i=;i<lim;i++)b[i]=((ll)b[i]+(ll)tt[i]*t[i])%mod*inv2%mod;
ntt(b,-,lim);
for(int i=n;i<lim;i++)b[i]=;
}
int main()
{
n=rd(); m=rd(); inv2=pw(,mod-);
for(int i=,x;i<=n;i++)x=rd(),c[x]++;
int lim=; while(lim<=m)lim<<=;//m
for(int i=;i<lim;i++)c[i]=((-(ll)*c[i])%mod+mod)%mod;//!1-4*c[i]! //(ll)!!
c[]=;//1+!!
sqt(c,sc,lim);//lim
sc[]++; sc[]=upt(sc[]);
inv(sc,f,lim);
for(int i=;i<=m;i++)printf("%d\n",upt(f[i]<<));
return ;
}
CF 438 E & bzoj 3625 小朋友和二叉树 —— 多项式开方的更多相关文章
- bzoj 3625小朋友和二叉树 多项式求逆+多项式开根 好题
题目大意 给定n种权值 给定m \(F_i表示权值和为i的二叉树个数\) 求\(F_1,F_2...F_m\) 分析 安利博客 \(F_d=F_L*F_R*C_{mid},L+mid+R=d\) \( ...
- BZOJ 3625:小朋友和二叉树 多项式开根+多项式求逆+生成函数
生成函数这个东西太好用了~ code: #include <bits/stdc++.h> #define ll long long #define setIO(s) freopen(s&q ...
- [Codeforces438E][bzoj3625] 小朋友和二叉树 [多项式求逆+多项式开根]
题面 传送门 思路 首先,我们把这个输入的点的生成函数搞出来: $C=\sum_{i=0}^{lim}s_ix^i$ 其中$lim$为集合里面出现过的最大的数,$s_i$表示大小为$i$的数是否出现过 ...
- [BZOJ3625][Codeforces Round #250]小朋友和二叉树 多项式开根+求逆
https://www.lydsy.com/JudgeOnline/problem.php?id=3625 愉快地列式子.设\(F[i]\)表示权值为\(i\) 的子树的方案数,\(A[i]\)为\( ...
- BZOJ #3625 CF #438E 小朋友和二叉树
清真多项式题 BZOJ #3625 codeforces #438E 题意 每个点的权值可以在集合$ S$中任取 求点权和恰好为$[1..n]$的不同的二叉树数量 数据范围全是$ 10^5$ $ So ...
- BZOJ 3625: [Codeforces Round #250]小朋友和二叉树
3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 304 Solved: 13 ...
- [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)
[BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...
- 「BZOJ 3645」小朋友与二叉树
「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...
- 【bzoj3625】【xsy1729】小朋友和二叉树
[bzoj3625]小朋友与二叉树 题意 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. 考虑一个含有n个互异正整数的序列c[1],c[2],...,c[n].如果一棵带点权的有根二叉树满足其所有 ...
随机推荐
- Ubuntu下安装和编译ffmpeg
参考:http://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu 1.安装依赖包 sudo apt-get update sudo apt-get -y ...
- 自我总结- CGAffineTransform
在应用中我们经常需要做一些仿射变换 可以用于 平移.旋转.缩放变换路径: View有一个属性transform 可以指定一个 CGAffineTransform 即可完成仿射变换 1.平移变换 // ...
- 在ios中使用单例模式编程
本文转载至 http://blog.csdn.net/remote_roamer/article/details/7107007 1. @implementation Singleton ...
- 公网yum 源地址
1. centos5.* 公网yum 源地址 [root@web ~]# cd /etc/yum.repos.d/[root@web yum.repos.d]# wget -O /etc/yum.r ...
- 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治
[BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...
- live555二次开发经验总结:RTSPClient客户端与RTSPServer服务器
live555介绍 安防领域的流媒体开发者估计没有谁不知道live555的,可能并不是因为其架构有多牛,代码有多好看,而是因为这玩意存在的年限实在是太长了,从changelog来看,live555从2 ...
- 基于Flume的美团日志收集系统 架构和设计 改进和优化
3种解决办法 https://tech.meituan.com/mt-log-system-arch.html 基于Flume的美团日志收集系统(一)架构和设计 - https://tech.meit ...
- Jeff Dean 排序时间计算
Quicksort (sometimes called partition-exchange sort) https://en.m.wikipedia.org/wiki/Quicksort
- Method invoke 方法
这个问题要看明白源码才能解决
- 【题解】 P5021赛道修建
[题解]P5021 赛道修建 二分加贪心,轻松拿省一(我没有QAQ) 题干有提示: 输出格式: 输出共一行,包含一个整数,表示长度最小的赛道长度的最大值. 注意到没,最小的最大值,还要多明显? 那么我 ...