COGS 有标号的二分图计数系列
其实这三道题都是不错的……(虽然感觉第三题略套路了……)
分别写一下做法好了……
这个就很简单了,Noip难度。
显然可以直接认为黑点和白点分别位于二分图两侧,枚举二分图左侧的点数,如果左侧的点数为$k$,那么就有$C_n^k$种选择方案,并且有$k(n-k)$条边可选,因为每条边都可以选或不选,因此答案就是
\begin{align}\sum_{k=0}^n C_n^k 2^{k(n-k)}\end{align}
由于只需求出一个答案,直接快速幂搞一搞即可,复杂度$O(n\log n)$。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define fac(x) (((x)<(0))?(0):(f[(x)]))
using namespace std;
const int maxn=;
const LL p=998244353ll;
LL inv(LL);
LL qpow(LL,LL);
LL C(int,int);
int n;
LL f[maxn<<],ans=;
int main(){
#define MINE
#ifdef MINE
freopen("QAQ_bipartite_one.in","r",stdin);
freopen("QAQ_bipartite_one.out","w",stdout);
#endif
scanf("%d",&n);
f[]=1ll;
for(int i=;i<=n;i++)f[i]=f[i-]*i%p;
for(int i=;i<=n;i++)(ans+=C(n,i)*qpow(2ll,(LL)(n-i)*i%(p-1ll)))%=p;
printf("%d",(int)ans);
return ;
}
LL inv(LL x){
return qpow(x,p-2ll);
}
LL qpow(LL a,LL b){
LL ans=1ll;
for(;b;b>>=,(a*=a)%=p)if(b&1ll)(ans*=a)%=p;
return ans;
}
LL C(int n,int m){
return fac(n)*inv(fac(m)*fac(n-m)%p)%p;
}
(这代码是我很久之前写的了,十分丑陋,不要介意……)
设上一题的指数生成函数是$F(x)$,这题的指数生成函数为$G(x)$,强制必须连通的指数生成函数是$H(x)$,显然有
\begin{align}G=\sum_{i=0}^\infty\frac{H^i}{i!}=e^{H}\end{align}
然后考虑$F$和$H$的关系,如果某个二分图有$k$个连通块,那么它在第一题中就会被计算$2^k$次,所以我们需要把每一项乘上$2^k$,因此就有
\begin{align}F=\sum_{i=0}^\infty\frac{2^iH^i}{i!}=e^{2H}\end{align}
然后可以看出来$F=G^2$,也就是$G=\sqrt F$,跑一下多项式开根即可求出$G$。
但是还有一个最重要的问题,这个$F$不好算……
$F$显然是没法直接算了,但观察到$F$的形式和卷积比较像,因此我们可以尝试把$F$化成卷积形式。显然最碍事的就是$2^{n(n-k)}$了,只要解决掉它,一切就都好说了。
首先我们有$k(n-k)=k^2-nk$,把$nk$用$\frac{n^2+k^2-(n-k)^2}2$替换之后就可以得到$k(n-k)=\frac{n^2-k^2-(n-k)^2}2$,因此$2^{k(n-k)}=\frac{\left(\sqrt 2\right)^{n^2}}{\left(\sqrt 2\right)^{k^2}\left(\sqrt 2\right)^{(n-k)^2}}$,然后就是卷积形式了,一遍NTT即可求出$F$。
ps:我没有想出来,这是看了ad学长的题解才明白的,感觉还是比较妙啊……
在$\mod 998244353$意义下是存在$\sqrt 2$的,暴力一下并把暴力出的答案直接写到代码里即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,p=,g=,sqrt_2=,inv_2=;
void NTT(int*,int,int);
void getsqrt(int*,int*,int);
void getinv(int*,int*,int);
int qpow(int,int,int);
int n,N=,A[maxn],B[maxn],fac[maxn],pw[maxn];
int main(){
freopen("QAQ_bipartite_two.in","r",stdin);
freopen("QAQ_bipartite_two.out","w",stdout);
scanf("%d",&n);
while(N<=n)N<<=;
A[]=fac[]=pw[]=;
for(int i=;i<=n;i++){
fac[i]=(long long)fac[i-]*i%p;
pw[i]=qpow(sqrt_2,(long long)i*i%(p-),p);
A[i]=qpow((long long)fac[i]*pw[i]%p,p-,p);
}
NTT(A,N<<,);
for(int i=;i<(N<<);i++)A[i]=(long long)A[i]*A[i]%p;
NTT(A,N<<,-);
for(int i=;i<=n;i++)A[i]=(long long)A[i]*pw[i]%p;
fill(A+n+,A+(N<<),);
getsqrt(A,B,N);
printf("%d",(int)((long long)B[n]*fac[n]%p));
return ;
}
void NTT(int *A,int n,int tp){
for(int i=,j=,k;i<n-;i++){
k=n;
do j^=(k>>=);while(j<k);
if(i<j)swap(A[i],A[j]);
}
for(int k=;k<=n;k<<=){
int wn=qpow(g,(tp>?(p-)/k:(p-)/k*(long long)(p-)%(p-)),p);
for(int i=;i<n;i+=k){
int w=;
for(int j=;j<(k>>);j++,w=(long long)w*wn%p){
int a=A[i+j],b=(long long)w*A[i+j+(k>>)]%p;
A[i+j]=(a+b)%p;
A[i+j+(k>>)]=(a-b+p)%p;
}
}
}
if(tp<){
int inv=qpow(n,p-,p);
for(int i=;i<n;i++)A[i]=(long long)A[i]*inv%p;
}
}
void getsqrt(int *A,int *C,int n){
static int B[maxn],D[maxn];
fill(C,C+(n<<),);
C[]=;
for(int k=;k<=n;k<<=){
copy(A,A+k,B);
fill(B+k,B+(k<<),);
getinv(C,D,k);
NTT(B,k<<,);
NTT(D,k<<,);
for(int i=;i<(k<<);i++)B[i]=(long long)B[i]*D[i]%p;
NTT(B,k<<,-);
for(int i=;i<k;i++)C[i]=(long long)(C[i]+B[i])*inv_2%p;
}
}
void getinv(int *A,int *C,int n){
static int B[maxn];
fill(C,C+(n<<),);
C[]=qpow(A[],p-,p);
for(int k=;k<=n;k<<=){
copy(A,A+k,B);
fill(B+k,B+(k<<),);
NTT(B,k<<,);
NTT(C,k<<,);
for(int i=;i<(k<<);i++)C[i]=C[i]*((-(long long)B[i]*C[i]%p+p)%p)%p;
NTT(C,k<<,-);
fill(C+k,C+(k<<),);
}
}
int qpow(int a,int b,int p){
int ans=;
for(;b;b>>=,a=(long long)a*a%p)if(b&)ans=(long long)ans*a%p;
return ans;
}
你还记得$F=e^{2H}$不……
然后就很好说了,多项式$\ln$之后答案就是对应项系数$/2$……
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,p=,g=,sqrt_2=,inv_2=;
void NTT(int*,int,int);
void getln(int*,int*,int);
void getinv(int*,int*,int);
void getderivative(int*,int*,int);
void getintegrate(int*,int*,int);
int qpow(int,int,int);
int n,N=,A[maxn],B[maxn],fac[maxn],pw[maxn];
int main(){
freopen("QAQ_bipartite_thr.in","r",stdin);
freopen("QAQ_bipartite_thr.out","w",stdout);
scanf("%d",&n);
while(N<=n)N<<=;
A[]=fac[]=pw[]=;
for(int i=;i<=n;i++){
fac[i]=(long long)fac[i-]*i%p;
pw[i]=qpow(sqrt_2,(long long)i*i%(p-),p);
A[i]=qpow((long long)fac[i]*pw[i]%p,p-,p);
}
NTT(A,N<<,);
for(int i=;i<(N<<);i++)A[i]=(long long)A[i]*A[i]%p;
NTT(A,N<<,-);
for(int i=;i<=n;i++)A[i]=(long long)A[i]*pw[i]%p;
fill(A+n+,A+(N<<),);
getln(A,B,N);
printf("%d",(int)((long long)B[n]*fac[n]%p*inv_2%p));
return ;
}
void NTT(int *A,int n,int tp){
for(int i=,j=,k;i<n-;i++){
k=n;
do j^=(k>>=);while(j<k);
if(i<j)swap(A[i],A[j]);
}
for(int k=;k<=n;k<<=){
int wn=qpow(g,(tp>?(p-)/k:(p-)/k*(long long)(p-)%(p-)),p);
for(int i=;i<n;i+=k){
int w=;
for(int j=;j<(k>>);j++,w=(long long)w*wn%p){
int a=A[i+j],b=(long long)w*A[i+j+(k>>)]%p;
A[i+j]=(a+b)%p;
A[i+j+(k>>)]=(a-b+p)%p;
}
}
}
if(tp<){
int inv=qpow(n,p-,p);
for(int i=;i<n;i++)A[i]=(long long)A[i]*inv%p;
}
}
void getln(int *A,int *C,int n){
static int B[maxn];
getderivative(A,B,n);
getinv(A,C,n);
NTT(B,n<<,);
NTT(C,n<<,);
for(int i=;i<(n<<);i++)B[i]=(long long)B[i]*C[i]%p;
NTT(B,n<<,-);
getintegrate(B,C,n);
fill(C+n,C+(n<<),);
}
void getinv(int *A,int *C,int n){
static int B[maxn];
fill(C,C+(n<<),);
C[]=qpow(A[],p-,p);
for(int k=;k<=n;k<<=){
copy(A,A+k,B);
fill(B+k,B+(k<<),);
NTT(B,k<<,);
NTT(C,k<<,);
for(int i=;i<(k<<);i++)C[i]=C[i]*((-(long long)B[i]*C[i]%p+p)%p)%p;
NTT(C,k<<,-);
fill(C+k,C+(k<<),);
}
}
void getderivative(int *A,int *C,int n){
for(int i=;i<n;i++)C[i-]=(long long)A[i]*i%p;
C[n-]=;
}
void getintegrate(int *A,int *C,int n){
for(int i=;i<n;i++)C[i]=(long long)A[i-]*qpow(i,p-,p)%p;
C[]=;
}
int qpow(int a,int b,int p){
int ans=;
for(;b;b>>=,a=(long long)a*a%p)if(b&)ans=(long long)ans*a%p;
return ans;
}
COGS 有标号的二分图计数系列的更多相关文章
- COGS 2392 2393 2395 有标号的二分图计数
有黑白关系: 枚举左部点(黑色点),然后$2^{i*(n-i)}$处理方法同:COGS 2353 2355 2356 2358 有标号的DAG计数 无关系: 发现,假设$f(i)$是一个连通块,对于一 ...
- cogs [HZOI 2015]有标号的二分图计数
题目分析 n个点的二分染色图计数 很显然的一个式子 \[ \sum_{i=0}^n\binom{n}{i}2^{i(n-i)} \] 很容易把\(2^{i(n-i)}\)拆成卷积形式,前面讲过,不再赘 ...
- 有标号的DAG计数系列问题
传送门 II 设 \(f_i\) 表示 \(i\) 个点的答案 那么枚举至少 \(j\) 个点的出度为 \(0\) \[\sum_{j=0}^{i}(-1)^j\binom{i}{j}f_{i-j}2 ...
- COGS 2353 2355 2356 2358 有标号的DAG计数
不用连通 枚举入度为0的一层 卷积 发现有式子: 由$n^2-i^2-(n-i)^2=2*i*(n-i)$ 可得$2^{i*(n-i)}=\frac{{\sqrt 2}^{(n^2)}}{{\sqrt ...
- 有标号的DAG计数(FFT)
有标号的DAG计数系列 有标号的DAG计数I 题意 给定一正整数\(n\),对\(n\)个点有标号的有向无环图(可以不连通)进行计数,输出答案\(mod \ 10007\)的结果.\(n\le 500 ...
- COGS 2396 2397 [HZOI 2015]有标号的强连通图计数
题意:求n个点有向图其中SCC是一个的方案数 考虑求出若干个不连通的每个连通块都是SCC方案数然后再怎么做一做.(但是这里不能用Ln,因为推不出来) 设$f_n$为答案, $g_n$为n个点的有向图, ...
- COGS 有标号的DAG/强连通图计数
COGS索引 一堆神仙容斥+多项式-- 有标号的DAG计数 I 考虑\(O(n^2)\)做法:设\(f_i\)表示总共有\(i\)个点的DAG数量,转移考虑枚举DAG上所有出度为\(0\)的点,剩下的 ...
- COGS2356 【HZOI2015】有标号的DAG计数 IV
题面 题目描述 给定一正整数n,对n个点有标号的有向无环图进行计数. 这里加一个限制:此图必须是弱连通图. 输出答案mod 998244353的结果 输入格式 一个正整数n. 输出格式 一个数,表示答 ...
- COGS2355 【HZOI2015】 有标号的DAG计数 II
题面 题目描述 给定一正整数n,对n个点有标号的有向无环图(可以不连通)进行计数,输出答案mod 998244353的结果 输入格式 一个正整数n 输出格式 一个数,表示答案 样例输入 3 样例输出 ...
随机推荐
- iOS开发中UILocalNotification本地通知实现简单的提醒功能
这段时间项目要求做一个类似的闹钟提醒功能,对通知不太熟悉的我,决定先用到xcode自带的本地通知试试,最终成功的实现了功能,特整理分享下. 它的表现特点: app关闭的时候也能接收和显示通知. app ...
- 2016级算法第四次上机-D.AlvinZH的1021实验plus
978 AlvinZH的1021实验plus 思路 贪心,中等题. 使用miss变量表示未覆盖的最小数字,初始值为1. 初始覆盖区间为[1,miss),目标是覆盖[1,m],即miss需要大于m. 需 ...
- Hibernate 初识
第一步: 导包:(这是我根据其他网站的介绍导入的包,可能不完善,但开发没什么问题,遇到问题再说) 当然还有mysql的jar包 第二步:进行hibernate环境配置 在classpath目录下建立h ...
- Maven环境下面多项目之间的引用
如图: https://github.com/sdl/odata-example sdl OData例子包含了4个项目,下载到本地后编译.发现只有model项目是可以编译过去了.其他几个暂时编译不过 ...
- Windows下安装Redis服务(zip)
1.官方没有 Windows版本的 Redis,官网介绍: Redis项目不正式支持Windows.但是,微软开发并维护了针对Win64的Windows版本. 2.Windows版本下载地址:http ...
- 移动端尺寸新写法-rem
rem这是个低调的css单位,近一两年开始崭露头角,有许多同学对rem的评价不一,有的在尝试使用,有的在使用过程中遇到坑就弃用了.但是我对rem综合评价是用来做web app它绝对是最合适的人选之一. ...
- 获取浏览器用户代理(user-agent)
获取浏览器用户代理(user-agent) 用户代理(user-agent)是浏览器客户端与服务器交互时的重要信息之一,用于帮助网站识别请求用户的浏览器类别,以便于网站发送相应的网页数据. 用户代理数 ...
- [总]Android高级进阶之路
个人Android高级进阶之路,目前按照这个目录执行,执行完毕再做扩展!!!!! 一.View的绘制 1)setContentView()的源码分析 2)SnackBar的源码分析 3)利用decor ...
- GCC 7.3.0版本编译http-parser-2.1问题
http-paser是一个用c编写的http消息解析器,地址:https://github.com/nodejs/http-parser,目前版本2.9 今天用gcc 7.3.0编译其2.1版本时,编 ...
- 微信小程序踩坑
微信小程序自定义属性data-xx使用注意事项 data-xx采用驼峰式命名时,数据传递打印显示(以jxsName与jxsname打印显示对比) data-xx全小写命名时,数据传递打印显示