【BZOJ4671】 异或图

Description

定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与

G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中, 否则这条边不在 G 中.

现在给定 s 个结点数相同的图 G1...s, 设 S = {G1, G2, . . . , Gs}, 请问 S 有多少个子集的异

或为一个连通图?

Input

第一行为一个整数s, 表图的个数.

接下来每一个二进制串, 第 i 行的二进制串为 gi, 其中 gi 是原图通过以下伪代码转化得

到的. 图的结点从 1 开始编号, 下面设结点数为 n.

Algorithm 1 Print a graph G = (V, E)

for i = 1 to n do

for j = i + 1 to n do

if G contains edge (i, j) then

print 1

else

print 0

end if

end for

end for

2 ≤ n ≤ 10,1 ≤ s ≤ 60.

Output

输出一行一个整数, 表示方案数

Sample Input

3
1
1
0

Sample Output

4

HINT

Solution

这道题的出处是去年我们省的省队集训。

回想起去年省队集训的时候,非正式选手的我看到这道题和这道题题解时的一脸懵逼。

“为什么是2^全零行个数次方啊?”

“斯特林数是啥子啊?”

“贝尔数又是啥子啊?”

“这题为什么我看了题解还是不知道怎么做啊?”

“为什么标程的代码这么短啊?”

“……”

时隔了整整一年,重新拿到这道题,感慨颇多。

首先,连通的条件并不好算,我们考虑不连通的情况。

我们先枚举一个划分,表示不同的划分里的点一定在不同的连通块,但在同一个划分里的点不一定在同一个连通块。也就是说所有连接两个不同划分的边都必须为0。这个的方案数可以用高斯消元算,答案会等于2^s-基的个数。

然后我们再考虑每种方案都被重复算了多少遍。一个划分集合如果是另一个划分集合的子集的话那么它被重复算的系数是斯特林数,我们可以暴力把这个容斥系数算出来(如果打表打出来会发现其实是阶乘)。

复杂度是贝尔数的第N项*高斯消元的。

代码的确很短。

Code

 1 #include <cstdio>
 2 #include <bitset>
 3 #include <cstring>
 4 #define R register
 5 typedef long long ll;
 6 char str[110];
 7 int s, n, id[110][110], len;
 8 std::bitset<110> b[66], t, c[66];
 9 int col[11];
10 ll pw[66], ans, f[110], S[110][110];
11 void dfs(R int x, R int cl)
12 {
13     if (x > n)
14     {
15         R int cnt = 0, ji = 0;
16         for (R int i = 1; i <= n; ++i)
17             for (R int j = i + 1; j <= n; ++j)
18                 if (col[i] != col[j]) t.set(cnt), ++cnt;
19                 else t.reset(cnt), ++cnt;
20         for (R int i = 1; i <= s; ++i)
21         {
22             c[i] = b[i] & t;
23 //            for (R int j = 0; j < len; ++j) printf("%d", c[i][j] == 1); puts("");
24         }
25         for (R int i = 1, bs = 0; i <= s && bs < len; )
26         {
27             if (c[i][bs] == 0)
28             {
29                 for (R int j = i + 1; j <= s; ++j)
30                     if (c[j][bs])
31                     {
32                         std::swap(c[i], c[j]);
33                         break;
34                     }
35             }
36             if (c[i][bs] == 0) {++bs; continue;}
37             ++ji;
38             for (R int j = i + 1; j <= s; ++j)
39                 if (c[j][bs])
40                     c[j] ^= c[i];
41             ++i; ++bs;
42         }
43 //        for (R int i = 1; i <= n; ++i) printf("%d ", col[i]); puts("");
44 //        printf("base %d pw %lld\n", ji, f[cl] * pw[s - ji]);
45         ans += f[cl] * pw[s - ji];
46         return ;
47     }
48     for (R int i = 1; i <= cl; ++i)
49     {
50         col[x] = i;
51         dfs(x + 1, cl);
52     }
53     col[x] = cl + 1;
54     dfs(x + 1, cl + 1);
55 }
56 int main()
57 {
58     scanf("%d", &s);
59     pw[0] = 1;
60     for (R int i = 1; i <= s; ++i)
61     {
62         scanf("%s", str); pw[i] = pw[i - 1] * 2;
63         len = strlen(str);
64         for (n = 2; n <= 10; ++n) if (n * (n - 1) == len * 2) break;
65         for (R int j = 0; j < len; ++j) b[i][j] = (str[j] == ‘1‘);
66     }
67 //    for (R int i = 1; i <= s; ++i) {for (R int j = 0; j < len; ++j) printf("%d", b[i][j] == 1); puts("");}
68     S[1][1] = 1;
69     for (R int i = 2; i <= n; ++i)
70     {
71         S[i][1] = 1;
72         for (R int j = 2; j <= i; ++j)
73             S[i][j] = S[i - 1][j - 1] + j * S[i - 1][j];
74     }
75     f[1] = 1;
76     for (R int i = 2; i <= n; ++i)
77     {
78         for (R int j = i - 1; j; --j)
79             f[i] -= S[i][j] * f[j];
80 //        printf("%lld\n", f[i]);
81     }
82     R int cnt = 0;
83     for (R int i = 1; i <= n; ++i)
84         for (R int j = i + 1; j <= n; ++j)
85             id[i][j] = id[j][i] = cnt++;
86     dfs(1, 0);
87     printf("%lld\n", ans);
88     return 0;
89 }
90 /*
91 3
92 111
93 111
94 111
95 */
时间: 2024-07-30 12:53:22

【BZOJ4671】 异或图的相关文章

bzoj4671: 异或图

Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中, 否则这条边不在 G 中. 现在给定 s 个结点数相同的图 G1...s, 设 S = {G1, G2, . . . , Gs}, 请问 S 有多少个子集的异 或为一个连通图? Input 第一行为一个整数s, 表图的个数. 接下来每一个二进制串, 第 i 行的二进制串为 gi, 其中 gi 是原图通过

bzoj 4671: 异或图

4671: 异或图 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 61  Solved: 39[Submit][Status][Discuss] Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中, 否则这条边不在 G 中. 现在给定 s 个结点数相同的图 G1...s, 设 S = {G1, G2, .

【XSY2701】异或图 线性基 容斥原理

题目描述 定义两个图\(G_1\)与\(G_2\)的异或图为一个图\(G\),其中图\(G\)的每条边在\(G_1\)与\(G_2\)中出现次数和为\(1\). 给你\(m\)个图,问你这\(m\)个图组成的集合有多少个子集的异或图为一个连通图. \(n\leq 10,m\leq 60\) 题解 考虑枚举图的子集划分,让被划分到不同子集的点之间没有连边,而在同一个子集里面的点可以连通,可以不连通. 可以用高斯消元(线性基)得到满足条件的图的个数.设枚举的子集划分有\(k\)个集合,那么容斥系数就

【bzoj4671】异或图(容斥+斯特林反演+线性基)

传送门 题意: 给出\(s,s\leq 60\)张图,每张图都有\(n,n\leq 10\)个点. 现在问有多少个图的子集,满足这些图的边"异或"起来后,这张图为连通图. 思路: 直接考虑判断图的连通不好判断,所以考虑枚举连通块来进行容斥. 定义\(f_i\)表示有\(i\)个连通块的答案,发现连通块这个东西也不好处理,我们只能处理出有多少个连通块,但无法确定每个连通块内部的连通关系. 定义\(g_i\)为至少有\(i\)个连通块的方案数,那么就有关系式:\(\displaystyle

【bzoj 4671】 异或图

题目 神仙题啊神仙题 显然这个东西一脸不可求的样子啊,这种东西我们显然需要搞一个容斥什么的 于是设\(g_i\)表示至少存在\(i\)个联通块(联通块内部的边没有要求,联通块和联通块之间不存在边)的方案数,\(f_i\)表示恰有\(i\)个联通块 有 \[g_x=\sum_{i=x}^n\begin{Bmatrix}i\\x\end{Bmatrix}f_i\] 即我们对于那些联通块个数多于\(x\)个的情况,可以把这\(i\)个联通快分成\(k\)组,每一组作为一个新的"联通块",于是

bzoj 4671 异或图 —— 容斥+斯特林反演+线性基

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671 首先,考虑容斥,就是设 \( t[i] \) 表示至少有 \( i \) 个连通块的方案数: 我们希望得到恰好有一个连通块的方案数,但这里不能直接 \( + t[1] - t[2] + t[3] - t[4] ... \),因为每个"恰好 \( i \) 个连通块"的情况并不是在各种 \( t[j] ( j<=i ) \) 中只被算了一次,而是因为标号,被算了 \(

基于网络的 Red Hat 无人值守安装

基于网络的 Red Hat 无人值守安装 本文介绍了 PC 平台上的一种快速 Red Hat Linux 安装方案.它具有很高的自动化程度--用户只需手工启动机器并选择从网络启动,就可以完成整个安装过程.在需要批量安装大量 Red Hat Linux 系统和需要技术人员 Red Hat Linux 安装支持的情况下,这种方案可以节省大量的时间.而且由于不需要额外的软件和光驱和软驱等硬件设备,在成本上也有很大优势.所有安装 Red Hat Linux 的开发/测试人员,和 IT 支持人员都能够从本

村田噪声抑制基础教程-第一章 需要EMI静噪滤波器的原因

1-1. 简介 EMI静噪滤波器 (EMIFIL®) 是为电子设备提供电磁噪声抑制的电子元件,配合屏蔽罩和其他保护装置一起使用.这种滤波器仅从通过连线传导的电流中提取并移除引起电磁噪声的元件.第1章说明了电子设备中使用EMI静噪滤波器(EMIFIL®)的原因,还概述了通常电磁噪声抑制所用的典型屏蔽和滤波器的操作. 图1-1 EMI静噪滤波器 (EMIFIL®) 1-2. 什么是电磁噪声干扰? 电子设备收到强电磁波时,电路中会感应到不想要的电流,这会产生非预想的操作或对预想的操作形成干扰.如果外部

如何鉴别二手车中的“不良品”

新车还是二手车?根据最新的二手车市场调查,新车市场突遇爆冷,二手车却异军图起.这跟国民的消费模式,和经济消费观有着直接的联系.那么问题来了,二手车市场那么火爆,难道你买的二手车就是性价比高的吗?别逗了,每个行业都会有些小道道的.二手车最怕的不良品,可能就怕遇到“泡水车”“火烧车”甚至是“事故车”.看到这些名字,都让人心惊胆颤.这样的二手车我们该怎么鉴别呢?  鉴别事故车,保证权益  如果你看中一部二手车,单看图片和外观是不行的.买东西需要的是保证质量,所以事故车鉴别的第一步就是要去查询这辆车子的