其实这三道题都是不错的……(虽然感觉第三题略套路了……)

分别写一下做法好了……

COGS2392 有标号的二分图计数 I

这个就很简单了,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;
}

(这代码是我很久之前写的了,十分丑陋,不要介意……)

COGS2393 有标号的二分图计数 II

设上一题的指数生成函数是$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;
}

COGS2395 有标号的二分图计数 III

你还记得$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 有标号的二分图计数系列的更多相关文章

  1. COGS 2392 2393 2395 有标号的二分图计数

    有黑白关系: 枚举左部点(黑色点),然后$2^{i*(n-i)}$处理方法同:COGS 2353 2355 2356 2358 有标号的DAG计数 无关系: 发现,假设$f(i)$是一个连通块,对于一 ...

  2. cogs [HZOI 2015]有标号的二分图计数

    题目分析 n个点的二分染色图计数 很显然的一个式子 \[ \sum_{i=0}^n\binom{n}{i}2^{i(n-i)} \] 很容易把\(2^{i(n-i)}\)拆成卷积形式,前面讲过,不再赘 ...

  3. 有标号的DAG计数系列问题

    传送门 II 设 \(f_i\) 表示 \(i\) 个点的答案 那么枚举至少 \(j\) 个点的出度为 \(0\) \[\sum_{j=0}^{i}(-1)^j\binom{i}{j}f_{i-j}2 ...

  4. 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 ...

  5. 有标号的DAG计数(FFT)

    有标号的DAG计数系列 有标号的DAG计数I 题意 给定一正整数\(n\),对\(n\)个点有标号的有向无环图(可以不连通)进行计数,输出答案\(mod \ 10007\)的结果.\(n\le 500 ...

  6. COGS 2396 2397 [HZOI 2015]有标号的强连通图计数

    题意:求n个点有向图其中SCC是一个的方案数 考虑求出若干个不连通的每个连通块都是SCC方案数然后再怎么做一做.(但是这里不能用Ln,因为推不出来) 设$f_n$为答案, $g_n$为n个点的有向图, ...

  7. COGS 有标号的DAG/强连通图计数

    COGS索引 一堆神仙容斥+多项式-- 有标号的DAG计数 I 考虑\(O(n^2)\)做法:设\(f_i\)表示总共有\(i\)个点的DAG数量,转移考虑枚举DAG上所有出度为\(0\)的点,剩下的 ...

  8. COGS2356 【HZOI2015】有标号的DAG计数 IV

    题面 题目描述 给定一正整数n,对n个点有标号的有向无环图进行计数. 这里加一个限制:此图必须是弱连通图. 输出答案mod 998244353的结果 输入格式 一个正整数n. 输出格式 一个数,表示答 ...

  9. COGS2355 【HZOI2015】 有标号的DAG计数 II

    题面 题目描述 给定一正整数n,对n个点有标号的有向无环图(可以不连通)进行计数,输出答案mod 998244353的结果 输入格式 一个正整数n 输出格式 一个数,表示答案 样例输入 3 样例输出 ...

随机推荐

  1. Beginning and Ending the Speech

    Beginning and Ending the Speech Just as musical plays need appropriate beginnings and endings, so do ...

  2. java使用freemarker导出复杂的excel表格

    正常导出excel表格使用的poi,但是导出复杂的excel有点困难,但是可以使用freemaker模板来导出复杂的excel. 1.都是先生成一个Excel表格的模板,最好是增加一行数据.具体看图里 ...

  3. js 实现tab栏切换效果

    效果图: 源码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  4. Flume启动运行时报错org.apache.flume.ChannelFullException: Space for commit to queue couldn't be acquired. Sinks are likely not keeping up with sources, or the buffer size is too tight解决办法(图文详解)

        前期博客 Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解) 问题详情 启动agent服务 [hadoop@master flume-1.7.0]$ ...

  5. Java学习笔记01

    1.原型设计: 将页面的模块.元素.人机交互的形式,利用线框描述的方法,将产品脱离皮肤状态下更加具体跟生动的进行表达. 2.下面的是使用PowerDesigner进行设计的持久层的层次结构图: 虚线三 ...

  6. Android Studio Gradle下载的包在哪里?

    C:\Users\Administrator\.gradle\caches\modules-2\files-2.1

  7. vue-cli 启动过项目步骤

    一. 安装 node.js 安装完成后,可以命令行工具中输入 node -v 和 npm -v,如果能显示出版本号,就说明安装成功. 二.安装webpack npm install webpack - ...

  8. Python——内部参数对外部实参的影响

    无论函数传递的参数的可变还是不可变,只要针对参数使用赋值语句,会在函数内部修改局部变量的引用,不会影响到外部变量的引用,而如果传递的参数是可变类型,在函数内部使用方法修改了数据的内容,同样会影响到外部 ...

  9. Oracle远程数据建物化视图(materialized)创建简单记录,以及DBLINK的创建

    目的:实现远程数据库访问及其相应表的定时同步 一.远程数据库dblink的创建 select * from dba_db_links; select * from user_sys_privs;--查 ...

  10. Leo-io 的C语言实现简单五子棋游戏观后感

    源代码: /************************************************************** ** 文 件 名:wuziqi.cpp ** 功    能:扫 ...