Solution -「AGC 016F」Games on DAG
\(\mathcal{Description}\)
Link.
给定一个含 \(n\) 个点 \(m\) 条边的 DAG,有两枚初始在 1 号点和 2 号点的棋子。两人博弈,轮流移动其中一枚棋子到邻接结点位置,无法移动者负。求 \(2^m\) 个边集中,加入图中能使先手必胜的方案数。答案对 \(10^9+7\) 取模。
\(n\le15\)。
\(\mathcal{Solution}\)
先从博弈角度思考:两枚棋子显然独立,那么先手必胜等价于 \(\operatorname{sg}(1)\not=\operatorname{sg}(2)\),其中,\(\operatorname{sg}\) 有
\]
在不同边集的情况中,\(\operatorname{adj}(u)\) 有所改变,所以情况不同。
接下来,方便起见,尝试计数 \(\operatorname{sg}(1)=\operatorname{sg}(2)\) 的情况。令 \(f(S)~(1,2\in S)\) 表示仅考虑点集 \(S\) 的导出子图时,\(\operatorname{sg}(1)=\operatorname{sg}(2)\) 的方案数。而 DP 中的“子问题”源于 \(\operatorname{sg}\) 函数中 \(\operatorname{mex}\) 的定义——如果我们挑除所有 \(\operatorname{sg}(u)=0\) 的 \(u\)(一定存在)及其邻接边,剩下的子图仍然是同类问题,只是所有 \(\operatorname{sg}\) 值减少 \(1\),不影响 DP 定义,这就是转移的雏形。具体地,枚举点集 \(T\subseteq S\),钦定其中所有点的 \(\operatorname{sg}\) 非 \(0\),考虑:
\(1,2\in T\),\(T\) 中每个点至少连向一个 \(S-T\) 中的点,其余边任意(注意 \(T\) 中的边是子问题,不考虑)。
\(1,2\not\in T\),已经满足条件,在上种情况的基础上加上 \(T\) 中边任选的方案,直接贡献。
综上,复杂度 \(\mathcal O(3^nn)\)。
\(\mathcal{Code}\)
/* Clearink */
#include <cstdio>
#define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i )
const int MAXN = 15, MAXM = MAXN * ( MAXN - 1 ) >> 1, MOD = 1e9 + 7;
int n, m, pwr[MAXM + 5], conc[1 << MAXN][MAXN], f[1 << MAXN];
bool adj[MAXN + 5][MAXN + 5];
inline int mul( const long long a, const int b ) { return a * b % MOD; }
inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
int main() {
scanf( "%d %d", &n, &m ), pwr[0] = 1;
rep ( i, 1, m ) {
pwr[i] = add( pwr[i - 1], pwr[i - 1] );
int u, v; scanf( "%d %d", &u, &v );
adj[u - 1][v - 1] = true;
}
rep ( S, 1, ( 1 << n ) - 1 ) {
int v = 0; for ( ; !( S >> v & 1 ); ++v );
rep ( u, 0, n - 1 ) conc[S][u] = conc[S ^ 1 << v][u] + adj[u][v];
}
rep ( S, 0, ( 1 << n ) - 1 ) if ( ( S & 3 ) == 3 ) {
f[S] = 1;
for ( int T = S & ( S - 1 ); T; T = ( T - 1 ) & S ) {
if ( T & 1 && T & 2 ) {
int coe = 1;
rep ( u, 0, n - 1 ) if ( S >> u & 1 ) {
if ( T >> u & 1 ) {
coe = mul( coe, pwr[conc[S ^ T][u]] - 1 );
} else {
coe = mul( coe, pwr[conc[T][u]] );
}
}
addeq( f[S], mul( coe, f[T] ) );
} else if ( !( T & 1 || T & 2 ) ) {
int coe = 1;
rep ( u, 0, n - 1 ) if ( S >> u & 1 ) {
if ( T >> u & 1 ) {
coe = mul( coe,
mul( pwr[conc[S ^ T][u]] - 1, pwr[conc[T][u]] ) );
} else {
coe = mul( coe, pwr[conc[T][u]] );
}
}
addeq( f[S], coe );
}
}
}
printf( "%d\n", sub( pwr[m], f[( 1 << n ) - 1] ) );
return 0;
}
Solution -「AGC 016F」Games on DAG的更多相关文章
- Solution -「AGC 036D」「AT 5147」Negative Cycle
\(\mathcal{Descriprtion}\) Link. 在一个含 \(n\) 个结点的有向图中,存在边 \(\lang i,i+1,0\rang\),它们不能被删除:还有边 \(\l ...
- Solution -「AGC 026D」Histogram Coloring
\(\mathcal{Description}\) Link. 有 \(n\) 列下底对齐的方格纸排成一行,第 \(i\) 列有 \(h_i\) 个方格.将每个方格染成黑色或白色,求使得任意完 ...
- Solution -「AGC 004E」「AT 2045」Salvage Robots
\(\mathcal{Description}\) Link. 有一个 \(n\times m\) 的网格.每个格子要么是空的,要么有一个机器人,要么是一个出口(仅有一个).每次可以命令所有机 ...
- Solution -「AGC 012F」「AT 2366」Prefix Median
\(\mathcal{Description}\) Link. 给定序列 \(\{a_{2n-1}\}\),将 \(\{a_{2n-1}\}\) 按任意顺序排列后,令序列 \(b_i\) 为前 ...
- Solution -「AGC 010C」「AT 2304」Cleaning
\(\mathcal{Description}\) Link. 给定一棵 \(n\) 个点的无根树,点有点权,每次选择两个不同的叶子,使它们间的简单路径的所有点权 \(-1\),问能否将所有点 ...
- Solution -「AGC 019E」「AT 2704」Shuffle and Swap
\(\mathcal{Description}\) Link. 给定 \(01\) 序列 \(\{A_n\}\) 和 \(\{B_n\}\),其中 \(1\) 的个数均为 \(k\).记 \( ...
- Solution -「AGC 019F」「AT 2705」Yes or No
\(\mathcal{Description}\) Link. 有 \(n+m\) 个问题,其中 \(n\) 个答案为 yes,\(m\) 个答案为 no.每次你需要回答一个问题,然后得知这个 ...
- Solution -「AGC 013E」「AT 2371」Placing Squares
\(\mathcal{Description}\) Link. 给定一个长度为 \(n\) 的木板,木板上有 \(m\) 个标记点,第 \(i\) 个标记点距离木板左端点的距离为 \(x_i\ ...
- Solution -「AGC 003D」「AT 2004」Anticube
\(\mathcal{Description}\) Link. 给定 \(n\) 个数 \(a_i\),要求从中选出最多的数,满足任意两个数之积都不是完全立方数. \(n\le10^5\) ...
随机推荐
- 关于Vue中根组件与组件树的理解
在观看了b站的关于Vue3的教学视频后,对Vue的根组件与组件树进行简单的总结下 一.实例化Vue应用 // 此时,app就是一个Vue应用的实例,或者说是一个对象 const app = Vue.c ...
- Go 分布式令牌桶限流 + 兜底策略
上篇文章提到固定时间窗口限流无法处理突然请求洪峰情况,本文讲述的令牌桶线路算法则可以比较好的处理此场景. 工作原理 单位时间按照一定速率匀速的生产 token 放入桶内,直到达到桶容量上限. 处理请求 ...
- 解决excel两表之间数据关联关系,知道这几招就够了
用过SAP的凭证批量录入模板(Excel文件)的都知道,一个凭证由[抬头]和多个[行项目]组成,这是一个关于excel两表信息关联的典型场景. 这里头蕴藏着一个麻烦:当我们需要一次性录入多个凭证时,如 ...
- git文件管理与索引,深入理解工作原理
前言 这一夜,注定是个不眠之夜,小白和cangls的对话已然进入了白热化.小白孜孜不倦的咨询关于git方面的知识,对索引越来越感兴趣.小白以前存的小电影文件可以进行版本的对比,探索哪个版本画质更好. ...
- 【解决了一个小问题】golang的go.mod中出现版本错误
代码中的这一句使用prometheus2.28.0版本的代码: import "github.com/prometheus/prometheus/prompb" 我把require ...
- prometheus+exporter小测试:
1.golang中使用expoter import ( "github.com/prometheus/client_golang/prometheus/promhttp" ) fu ...
- 【失败经验分享】android下使用支持opencl的cv::dft()
1.使用了UMat,但是并未使用GPU计算 cv::dft()函数的定义是: void cv::dft( InputArray _src0, OutputArray _dst, int flags, ...
- Windows和Linux关闭占用端口
关闭端口的方式有很多种,但是常用的就是这种比较来的快一点 如果通过以下方式解决不了,可以通过关闭服务来解决 Windows 1.查看端口占用的进程 netstat -ano | findstr 800 ...
- gin框架中的路由拆分与注册
基本的路由注册 下面最基础的gin路由注册方式,适用于路由条目比较少的简单项目或者项目demo. package main import ( "net/http" "gi ...
- Go 变量及基本数据类型1
#### Go 变量及基本数据类型(一)今天主要学习一下Go 中的变量及基本数据类型: 如何申明,使用变量,以及基本数据类型的介绍和使用细节; ##### 变量的介绍1. 变量相当于内存中一个数据存储 ...