\(\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{sg}(u)=\operatorname{mex}_{v\in\operatorname{adj}(u)}\operatorname{sg}(v)
\]

在不同边集的情况中,\(\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的更多相关文章

  1. Solution -「AGC 036D」「AT 5147」Negative Cycle

    \(\mathcal{Descriprtion}\)   Link.   在一个含 \(n\) 个结点的有向图中,存在边 \(\lang i,i+1,0\rang\),它们不能被删除:还有边 \(\l ...

  2. Solution -「AGC 026D」Histogram Coloring

    \(\mathcal{Description}\)   Link.   有 \(n\) 列下底对齐的方格纸排成一行,第 \(i\) 列有 \(h_i\) 个方格.将每个方格染成黑色或白色,求使得任意完 ...

  3. Solution -「AGC 004E」「AT 2045」Salvage Robots

    \(\mathcal{Description}\)   Link.   有一个 \(n\times m\) 的网格.每个格子要么是空的,要么有一个机器人,要么是一个出口(仅有一个).每次可以命令所有机 ...

  4. Solution -「AGC 012F」「AT 2366」Prefix Median

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_{2n-1}\}\),将 \(\{a_{2n-1}\}\) 按任意顺序排列后,令序列 \(b_i\) 为前 ...

  5. Solution -「AGC 010C」「AT 2304」Cleaning

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的无根树,点有点权,每次选择两个不同的叶子,使它们间的简单路径的所有点权 \(-1\),问能否将所有点 ...

  6. Solution -「AGC 019E」「AT 2704」Shuffle and Swap

    \(\mathcal{Description}\)   Link.   给定 \(01\) 序列 \(\{A_n\}\) 和 \(\{B_n\}\),其中 \(1\) 的个数均为 \(k\).记 \( ...

  7. Solution -「AGC 019F」「AT 2705」Yes or No

    \(\mathcal{Description}\)   Link.   有 \(n+m\) 个问题,其中 \(n\) 个答案为 yes,\(m\) 个答案为 no.每次你需要回答一个问题,然后得知这个 ...

  8. Solution -「AGC 013E」「AT 2371」Placing Squares

    \(\mathcal{Description}\)   Link.   给定一个长度为 \(n\) 的木板,木板上有 \(m\) 个标记点,第 \(i\) 个标记点距离木板左端点的距离为 \(x_i\ ...

  9. Solution -「AGC 003D」「AT 2004」Anticube

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个数 \(a_i\),要求从中选出最多的数,满足任意两个数之积都不是完全立方数.   \(n\le10^5\) ...

随机推荐

  1. systemd学习及使用

    什么是systemd? (译)systemd是linux系统的一组基础构件块.它提供了一个系统和服务的管理,它以PID 1 的形式运行并启动系统的其余部分.systemd 使用积极的并行化功能,使用s ...

  2. centos7 date时间命令

    date "+%F %T" %F     full date; same as %Y-%m-%d  --相当于年月日格式 %T     time; same as %H:%M:%S ...

  3. LINUX学习-Nginx服务器的反向代理和负载均衡

    一.准备环境 1.准备3台服务器: 1)192.168.88.10 --Nginx服务器 2)192.168.88.20 --apache服务器 3)192.168.88.30 --apache服务器 ...

  4. leetcode 347. 前 K 个高频元素

    问题描述 给定一个非空的整数数组,返回其中出现频率前 k 高的元素.   示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums ...

  5. Cesium中文网的朋友们

    目前已开通知识星球-Cesium中文网的朋友们 注意:仔细思量好再进来,一旦付费,概不退费.下述内容均尽力而为. 1. 每月一次技术交流(Cesium为主),提供源码. 2. 每人5次/周免费提问(C ...

  6. 阿里Java规范:【强制】所有的 POJO 类属性必须使用包装数据类型

    在 Java 开发手册中有这一条: 我们知道基本类型和包装类型有很多不同点: 封装类型可以调用各种方法,而基本类型没有 封装类型声明字段之后可以不设置默认值,而基本类型需要初始化默认值.比如 int ...

  7. elementui表格里面的索引,多选的复用解决

    使用elementui表格时,当一个页面通过if判断有多个不同的表格时,其中一个或多个表格想要设置索引或者多选框时,会发现你在第一个里面设置了索引或者多选框,其他的表格都会出现,你在后面的其中一个设置 ...

  8. Android开发之事件

    当按下一个按钮时,有两种事件促发的方式,一种是通过回调,一种是通过事件监听. 回调: xml中: 只要设置android:onclick="回调函数名字" '主函数中重写回调函数即 ...

  9. gin框架中图形验证码的生成和验证

    功能和验证码使用原理 本案例中没有使用redis作为缓存,而是使用的内存存储方法 github链接地址 下载命令 go get github.com/mojocn/base64Captcha 请求处理 ...

  10. golang中字符串-字节切片,字符串-字符切片的互转

    package main import ( "fmt" "reflect" ) func B2S(bs []uint8) string { // 将字节切片转换 ...