loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)
题面
题解
肝了一个下午……我老是忘了拉格朗日反演计算的时候多项式要除以一个\(x\)……结果看它推倒简直一脸懵逼……
做这题首先你得知道拉格朗日反演是个什么东西->这里
请坐稳,接下来就要开始推倒了
首先我们要知道\(n\)个点的有根无向连通图的个数,带标号
设\(G(x)\)为\(n\)个点有根无向图的个数的生成函数,\(F(x)\)为\(n\)个点有根无向连通图的个数的生成函数,那么有\(G(x)=\sum_{i=1}^\infty 2^{i\choose 2}x^i\)以及\(F(x)=e^{G(x)}\)
我们记带标号有根无向连通图的生成函数为\(H(x)\),记\(b_k\)表示\(k+1\)个点在同一个点双中的方案树,以及\(B(x)=\sum_{k\geq 1}{b_k\over k!}x^k\)
考虑一个有根连通图,如果我们去掉根节点,那么整张图会分成若干个连通块,对于一个连通块,根节点一定和这个连通块中的一些点构成点双,且这个点双中不包含其他连通块里的点。那么我们把这个点双中的所有边都去掉,这个连通块又会分成若干个以这些点为根的小连通块,可以看做连通块由小连通块构成。那么我们枚举这个连通块中有多少个点和根节点构成了点双,一个连通块的贡献就是
\]
那么整个连通图就有
\]
我们现在已知\(H(x)\),要求\(B\)中某些元素的值(那些\(S\)中的元素)
推倒一下有
\]
我们设\(H^{-1}(x)={x\over e^{B(x)}}=x\),有\(H^{-1}(H(x))=x\),即\(H^{-1}(x)\)是\(H(x)\)的复合逆
然后继续推倒,得\(B(x)=\ln {x\over H^{-1}(x)}\)
于是我们就可以用拉格朗日反演求出\(H^{-1}(x)\)从而求得\(B(x)\)了
我们令\(G(H^{-1}(x))=B(x)=\ln {x\over H^{-1}(x)}\),从而可以推出\(G(H^{-1}(H(x)))=G(x)=\ln{H(x)\over x}\)
根据拉格朗日反演定理,我们就可以求出\([x^n]B(x)\)了
\]
不要忘了计算的时候\(H(x)\)要除掉一个\(x\)再带进去计算
每次计算一个值的复杂度为\(O(k\log k)\),总复杂度为\(O(m\log m)\)
我们记
\]
\]
则\(F(x)\)即为答案的生成函数,根据上面推倒的易知\(F^{-1}(x)={x\over e^{A(x)}}\),拉格朗日反演即可得到\(F(x)\)
\]
计算的时候后面那个要除以一个\(x\)!不要忘记!
然后没有然后了
//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=5e5+5,P=998244353,Gi=332748118;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R ll y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
return res;
}
int O[N],r[N],H[N],G[N],F[N],inv[N],fac[N],ifac[N],lim,l,n,m,len,x;
inline void init(R int len){
lim=1,l=0;while(lim<len)lim<<=1,++l;
fp(i,0,lim-1)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
void NTT(int *A,int ty){
fp(i,0,lim-1)if(i<r[i])swap(A[i],A[r[i]]);
for(R int mid=1;mid<lim;mid<<=1){
int I=(mid<<1),Wn=ksm(ty==1?3:Gi,(P-1)/I);O[0]=1;
fp(i,1,mid-1)O[i]=mul(O[i-1],Wn);
for(R int j=0;j<lim;j+=I)fp(k,0,mid-1){
int x=A[j+k],y=mul(O[k],A[j+k+mid]);
A[j+k]=add(x,y),A[j+k+mid]=dec(x,y);
}
}
if(ty==-1)for(R int i=0,inv=ksm(lim,P-2);i<lim;++i)A[i]=mul(A[i],inv);
}
void Inv(int *a,int *b,int len){
if(len==1)return b[0]=ksm(a[0],P-2),void();
Inv(a,b,len>>1);static int A[N],B[N];init(len<<1);
fp(i,0,len-1)A[i]=a[i],B[i]=b[i];
fp(i,len,lim-1)A[i]=B[i]=0;
NTT(A,1),NTT(B,1);
fp(i,0,lim-1)A[i]=mul(A[i],mul(B[i],B[i]));
NTT(A,-1);
fp(i,0,len-1)b[i]=dec(add(b[i],b[i]),A[i]);
fp(i,len,lim-1)b[i]=0;
}
void Ln(int *a,int *b,int len){
static int A[N],B[N];
fp(i,1,len-1)A[i-1]=mul(a[i],i);A[len-1]=0;
Inv(a,B,len);init(len<<1);fp(i,len,lim-1)A[i]=B[i]=0;
NTT(A,1),NTT(B,1);
fp(i,0,lim-1)A[i]=mul(A[i],B[i]);
NTT(A,-1);
fp(i,1,len-1)b[i]=mul(A[i-1],inv[i]);b[0]=0;
fp(i,len,lim-1)b[i]=0;
}
void Exp(int *a,int *b,int len){
if(len==1)return b[0]=1,void();
Exp(a,b,len>>1);static int A[N];
Ln(b,A,len),init(len<<1);
A[0]=dec(a[0]+1,A[0]);
fp(i,1,len-1)A[i]=dec(a[i],A[i]);
fp(i,len,lim-1)A[i]=b[i]=0;
NTT(A,1),NTT(b,1);
fp(i,0,lim-1)b[i]=mul(b[i],A[i]);
NTT(b,-1);
fp(i,len,lim-1)b[i]=0;
}
void Get(){
static int A[N];
fp(i,0,len-1)A[i]=mul(ksm(2,1ll*i*(i-1)>>1),ifac[i]);
Ln(A,H,len);
fp(i,0,len-2)H[i]=mul(H[i+1],i+1);H[len-1]=0;
fp(i,0,len-1)A[i]=H[i];
Ln(A,G,len);
fp(i,0,len-2)G[i]=mul(G[i+1],i+1);G[len-1]=0;
fp(i,0,len-1)A[i]=H[i];
Ln(A,H,len);
}
int GetB(int n){
static int A[N],B[N];
len=1;while(len<=n)len<<=1;
fp(i,0,len-1)A[i]=1ll*H[i]*(P-n)%P;
Exp(A,B,len);init(len<<1);
fp(i,0,len-1)A[i]=G[i];
fp(i,len,lim-1)A[i]=B[i]=0;
NTT(A,1),NTT(B,1);
fp(i,0,lim-1)A[i]=mul(A[i],B[i]);
NTT(A,-1);
return mul(A[n-1],inv[n]);
}
int GetA(int n){
static int A[N];
len=1;while(len<=n)len<<=1;
fp(i,0,len-1)F[i]=mul(F[i],n);
Exp(F,A,len);
return 1ll*A[n-1]*inv[n]%P*fac[n-1]%P;
}
void Pre(){
inv[0]=inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
fp(i,2,len){
fac[i]=mul(fac[i-1],i);
inv[i]=mul(P-P/i,inv[P%i]);
ifac[i]=mul(ifac[i-1],inv[i]);
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
len=1;while(len<=n)len<<=1;
Pre(),Get();
while(m--)x=read()-1,F[x]=GetB(x);
printf("%d\n",GetA(n));
return 0;
}
loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)的更多相关文章
- bzoj3684: 大朋友和多叉树(拉格朗日反演+多项式全家桶)
题面 传送门 题解 首先你得知道什么是拉格朗日反演->这里 我们列出树的个数的生成函数 \[T(x)=x+\prod_{i\in D}T^i(x)\] \[T(x)-\prod_{i\in D} ...
- 【XSY2843】「地底蔷薇」 NTT什么的 扩展拉格朗日反演
题目大意 给定集合\(S\),请你求出\(n\)个点的"所有极大点双连通分量的大小都在\(S\)内"的不同简单无向连通图的个数对\(998244353\)取模的结果. \(n\le ...
- Loj #2495. 「AHOI / HNOI2018」转盘
Loj #2495. 「AHOI / HNOI2018」转盘 题目描述 一次小 G 和小 H 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1 ...
- Loj #2494. 「AHOI / HNOI2018」寻宝游戏
Loj #2494. 「AHOI / HNOI2018」寻宝游戏 题目描述 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得 ...
- loj#2020 「AHOI / HNOI2017」礼物 ntt
loj#2020 「AHOI / HNOI2017」礼物 链接 bzoj没\(letex\),差评 loj luogu 思路 最小化\(\sum\limits_1^n(a_i-b_i)^2\) 设改变 ...
- LOJ #2802. 「CCC 2018」平衡树(整除分块 + dp)
题面 LOJ #2802. 「CCC 2018」平衡树 题面有点难看...请认真阅读理解题意. 转化后就是,给你一个数 \(N\) ,每次选择一个 \(k \in [2, N]\) 将 \(N\) 变 ...
- LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)
题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
随机推荐
- 遍历js的obj中所有属性得key
var obj = $("#jstree_default").jstree("get_checked"); for (var a in obj) { alert ...
- Microsoft Sync Framework下的快速开发同步程序
Microsoft Sync Frameworks简称MSF,是一个综合的同步平台,MSF支持应用程序,服务,设备的在线以及离线同步.MSF主要有以下几个部件组成: * Sync Servic ...
- [Chapter 3 Process]Practice 3.2 Including the initial parent process, how many processes are created by the program shown in Figure?
3.2 Including the initial parent process, how many processes are created by the program shown in Fig ...
- 在.net中使用redis(StackExchange.Redis)
本文介绍如何在.net中使用redis 安装 代码使用 StackExchange.Redis基础使用 StackExchange.Redis中的事务 安装(windows平台) 安装Chocolat ...
- CentOS 7.2 部署Rsync + Lsyncd服务实现文件实时同步/备份 (三)
配置过程中遇到的错误与查看日志 以下错误是在服务正常开启的情况下发生的,请先查看服务是否正常启动. 一.错误 1. rsync: failed to set times on "." ...
- Canopy聚类算法(经典,看图就明白)
只有这个算法思想比较对,其他 的都没有一开始的remove: 原网址:http://www.shahuwang.com/?p=1021 Canopy Clustering 这个算法是2000年提出来的 ...
- redis学习四 复制
1,单机创建多实例 一个redis服务器安装多个redis实例,每个实例对应一个端口.默认端口是6379. 将redis.conf配置文件复制一份到另外一个文件夹下,然后修改其中的信息即可. pi ...
- 12-19Windows窗体应用程序之记事本(2)
之前记事本的功能实现了“文件”和“编辑”中的功能操作,现在再继续下面的功能介绍: 3) <1>字体设置 [查看代码] [效果图] <2>字体颜色的设置 [查看代码] [效果图] ...
- 问题:C# ToString("P");结果:c#中的常用ToString()方法总结
c#中的常用ToString()方法总结 很多类都重写了ToString方法, 导致很多类的tostring到底执行了什么,有哪些参数,都不清楚 对于int,double等的tostring: C ...
- 关于struts2.3的action
struts2.3中支持实时配置,也就是说不用在struts.xml中进行配置.但是所有的action文件应该放在有路径名含action的包中,否则程序无法发现你的action. 这个问题,难为了我好 ...