首页 > 其他分享 >「考试总结」2023-02-13 联合省选模拟赛 – Day1

「考试总结」2023-02-13 联合省选模拟赛 – Day1

时间:2023-02-13 22:15:03浏览次数:71  
标签:02 13 const 省选 LL texttt leq int 匹配

爆搜 $ \texttt {(dfs)} $

$ \texttt {Statement} $

给定一个 $ n $ 个点 $ m $ 条边的简单无向图,你需要对所有匹配 $ S $,把 $ c ^ { | S | } $ 求和,其中 $ | S | $ 是匹配的大小。对 $ 10 ^ 9 + 7 $ 取模。

一个匹配就是一个可以为空的边集,使得每个点至多是其中一条边的端点。

$ 1 \leq n \leq 36 $ ,$ 0 \leq m \leq \dfrac { n ( n - 1 ) } 2 $ ,$ 1 \leq c \leq 10 ^ 9 + 6 $

$ \texttt {Solution} $

新增一个零度的点是不会对答案造成影响的,因此可以加点使 $ n $ 为偶数,并且默认点的标号为 $ 0 \sim ( n - 1 ) $。

记匹配中的边为实边,在 点 $ 2 i $ 和 点 $ 2 i + 1 $ 之间连一条虚边,得到新匹配。
因为 每个点至多是其中一条边的端点,所以连上虚边之后每个点的度数不超过 $ 2 $。
因此对于一个连通块,它只可能是一条链或者一个简单环。
那么对于新匹配,就是若干条链和若干个环组成的简单图。

显然新匹配和原匹配是一一对应的。
考虑在新匹配拆成若干个连通块 $ \texttt {dp} $,再把每个连通块拼起来。
一个连通块再分成链和环两种情况计算。

巧妙之处在于通过连虚边的方式转换问题,而新问题中 $ 2i $ 和 $ 2i + 1 $ 一定是相连的,这样枚举点集的状态数就可以压缩至 $ 2 ^ { 0.5 n } \leq 2 ^ {18} $ 个了,比纯 $ \texttt { dp } $ 优化了很多。

计算环的方法与 $ \texttt {「CF11D」A Simple Task} $ 类似,注意下 $ 2i $ 和 $ 2i + 1 $ 是相连的即可。

这里只讲计算链的方法。

定义 $ f_{ s, i } $ 表示当前走过的点集为 $ s $,现在的终点为 $ i $ 的方案数。
枚举不在集合 $ s $ 中的点 $ j $,如果 $ i $ 和 $ j $ 之间实边相连,那么 $ f_{ t, j \texttt{ xor } 1 } \gets f_{ s, i } $,其中 $ t $ 表示 $ s $ 的集合中加入点 $ j $ 得到的新集合。$ j \texttt { xor } 1 $ 是因为点 $ j $ 与点 $ j \texttt { xor } 1 $ 之间一定有边相连,判断的是 $ i $ 和 $ j $,新的终点就是 $ j \texttt { xor } 1 $。

$ \texttt {Code} $

#include <cstdio>

#define LL long long
#define uLL unsigned LL

namespace Read {
	static const int buf_size = 1 << 12;
	static const bool use_fread = true;
	
	static unsigned char buf[buf_size];
	static int buf_len, buf_pos;
	
	bool isEOF() {
		if (buf_pos == buf_len) {
			buf_pos = 0; buf_len = fread(buf, 1, buf_size, stdin);
			if (buf_pos == buf_len) return true;
		}
		return false;
	}
	
	char readChar() {
		if (!use_fread) return getchar();
		return isEOF() ? EOF : buf[buf_pos++];
	}
	
	LL rint() {
		LL x = 0, Fx = 1; char c = readChar();
		while (c < '0' || c > '9') { Fx ^= (c == '-'); c = readChar(); }
		while ('0' <= c && c <= '9') { x = (x << 3) + (x << 1) + (c ^ 48); c = readChar(); }
		return Fx ? x : -x;
	}
	
	template <typename T>
	void read(T &x) {
		x = rint(); 
	}
	
	template <typename T, typename... Ts>
	void read(T &x, Ts &...rest) {
		read(x);
		read(rest...);
	}
} using namespace Read;

namespace Math {
	LL Max(LL u, LL v) { return (u > v) ? u : v; }
	LL Min(LL u, LL v) { return (u < v) ? u : v; }
} using namespace Math;

const int mod = 1e9 + 7;
const int inv = (mod + 1) >> 1;

const int MAX_n = 36;
const int MAX_m = 630;

const int mx = 1 << 18;

int n, m, c, up;

int qpow[MAX_n + 5];

int dp[mx + 5][MAX_n + 5];
int dpp[mx + 5][MAX_n + 5];

int dp1[mx + 5], dp2[mx + 5];

bool vis[MAX_n + 5][MAX_n + 5];

int main() {
	freopen("dfs.in", "r", stdin);
	freopen("dfs.out", "w", stdout);
	read(n, m, c); n += (n & 1); up = 1 << (n >>= 1);
	for (int i = 1, u, v; i <= m; i++)
		read(u, v), --u, --v, vis[u][v] = vis[v][u] = true;
	qpow[0] = 1 % mod;
	for (int i = 1; i <= n; i++)
		qpow[i] = (LL)qpow[i - 1] * c % mod;
	for (int i = 0; i < n; i++) {
		dp[1 << i][i << 1] = dp[1 << i][i << 1 | 1] = 1;
		dpp[1 << i][i << 1 | 1] = 1;
	}
	for (int S = 1; S < up; S++) {
		int siz = 0, id = 0;
		for (int i = 0; i < n; i++)
			if (S & (1 << i)) ++siz;
		for (int i = 0; i < n; i++) {
			if (S & (1 << i)) {
				int a = i << 1, b = i << 1 | 1;
				for (int j = 0; j < n; j++) {
					if (S & (1 << j)) continue;
					int x = j << 1, y = j << 1 | 1, T = S | (1 << j);
					if (vis[a][x]) dp[T][y] = (dp[T][y] + dp[S][a]) % mod;
					if (vis[a][y]) dp[T][x] = (dp[T][x] + dp[S][a]) % mod;
					if (vis[b][x]) dp[T][y] = (dp[T][y] + dp[S][b]) % mod;
					if (vis[b][y]) dp[T][x] = (dp[T][x] + dp[S][b]) % mod;
				}
			}
		}
		for (int i = 0; i < n; i++)
			if (S & (1 << i)) { id = i; break; }
		for (int i = id; i < n; i++) {
			if (S & (1 << i)) {
				int a = i << 1, b = i << 1 | 1;
				for (int j = id + 1; j < n; j++) {
					if (S & (1 << j)) continue;
					int x = j << 1, y = j << 1 | 1, T = S | (1 << j);
					if (vis[a][x]) dpp[T][y] = (dpp[T][y] + dpp[S][a]) % mod;
					if (vis[a][y]) dpp[T][x] = (dpp[T][x] + dpp[S][a]) % mod;
					if (vis[b][x]) dpp[T][y] = (dpp[T][y] + dpp[S][b]) % mod;
					if (vis[b][y]) dpp[T][x] = (dpp[T][x] + dpp[S][b]) % mod;
				}
			}
		}
		for (int j = 0; j < n; j++) {
			if (S & (1 << j)) {
				int x = j << 1, y = j << 1 | 1;
				dp1[S] = (dp1[S] + (LL)dp[S][x] * qpow[siz - 1] % mod * inv) % mod;
				dp1[S] = (dp1[S] + (LL)dp[S][y] * qpow[siz - 1] % mod * inv) % mod;
			}
		}
		for (int j = id; j < n; j++) {
			if (S & (1 << j)) {
				int x = j << 1, y = j << 1 | 1;
				if (vis[x][id << 1]) dp1[S] = (dp1[S] + (LL)dpp[S][x] * qpow[siz]) % mod;
				if (vis[y][id << 1]) dp1[S] = (dp1[S] + (LL)dpp[S][y] * qpow[siz]) % mod;
			}
		}
	}
	dp2[0] = 1 % mod;
	for (int S = 1; S < up; S++) {
		int siz = 0, id = 0;
		for (int i = 0; i < n; i++)
			if (S & (1 << i)) ++siz, id = i;
		for (int T = S; T & (1 << id); T = (S & (T - 1)))
			dp2[S] = (dp2[S] + (LL)dp2[S ^ T] * dp1[T]) % mod;
	}
	printf("%d\n", dp2[up - 1]);
	return 0;
}

标签:02,13,const,省选,LL,texttt,leq,int,匹配
From: https://www.cnblogs.com/DONGJIE-06/p/17117996.html

相关文章

  • 2023.2.13
    zroi2525分组钦定选中的人都被选到\(\text{A}\)组的概率,分别考虑枚举\(\text{A}\)组被放完和\(\text{B}\)组被放完的的方案数:记\(lst\)为最后一个被选中的人的......
  • GitLab CICD Day 02 - 什麼是 CICD
    ......
  • 2023.02.03
    继续凸优化,wqs二分+闵可夫斯基和,有点数据结构的味道wqs二分slopetrick闵可夫斯基和......
  • 闲话 23.2.13
    闲话机房歌单更新了(我写了一首《第三心脏》上去被muel和gtm说要指明miku唱的(我倒是觉得饭自己唱的也蛮好听的就是了今日推歌:无理无智不为什么只是最近老是哼......
  • Mybatis02 - 创建工程
    1、物理建模CREATEDATABASE`mybatis-example`;USE`mybatis-example`;CREATETABLE`t_emp`(emp_idINTAUTO_INCREMENT,emp_nameCHAR(100),emp_salaryD......
  • ideal的基础使用2022版本,黑马程序员的基础使用
    1.    2.配xml    <dependencies>    <dependency>        <groupId>javax.servlet</groupId>        <artifactId>javax.servl......
  • 2.13python基础知识
      编程语言的发展史1.机器语言:内部用0和1表示2.汇编语言:简单的字母表示二进制3.高级语言:人类可以理解的1、执行效率:机器语言>汇编语言>高级语言(编译型>解释型)2......
  • 省选联测31
    A.西克赛时冲了四个小时,在下行部分假了无数个做法。暴力两个log的话就倍增走一条重链,然后切重链,来回操作就行了。题解点击查看代码//ubsan:undefined//accod......
  • 记录一下2023.02.13
        今天是开学第一天,下午就进行了javaweb的测试,考试内容跟期末考试的差不多,都是实现增删改查,连接多个数据库,实现多个用户的操作。JDBC.Toolspackageutil;im......
  • 2022年下半年软考-软件设计师通过经验小记
    2021年末来了上海,考虑到要落户就考了中级软考。本人2022年下半年考的,上午53分,下午54分,低分通过。考试前看了很多别人的经验贴,考试通过了,来分享一下自己的经验贴。使用的......