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

 #include <cstdio>
#include <bitset>
#include <cstring>
#define R register
typedef long long ll;
char str[];
int s, n, id[][], len;
std::bitset<> b[], t, c[];
int col[];
ll pw[], ans, f[], S[][];
void dfs(R int x, R int cl)
{
if (x > n)
{
R int cnt = , ji = ;
for (R int i = ; i <= n; ++i)
for (R int j = i + ; j <= n; ++j)
if (col[i] != col[j]) t.set(cnt), ++cnt;
else t.reset(cnt), ++cnt;
for (R int i = ; i <= s; ++i)
{
c[i] = b[i] & t;
// for (R int j = 0; j < len; ++j) printf("%d", c[i][j] == 1); puts("");
}
for (R int i = , bs = ; i <= s && bs < len; )
{
if (c[i][bs] == )
{
for (R int j = i + ; j <= s; ++j)
if (c[j][bs])
{
std::swap(c[i], c[j]);
break;
}
}
if (c[i][bs] == ) {++bs; continue;}
++ji;
for (R int j = i + ; j <= s; ++j)
if (c[j][bs])
c[j] ^= c[i];
++i; ++bs;
}
// for (R int i = 1; i <= n; ++i) printf("%d ", col[i]); puts("");
// printf("base %d pw %lld\n", ji, f[cl] * pw[s - ji]);
ans += f[cl] * pw[s - ji];
return ;
}
for (R int i = ; i <= cl; ++i)
{
col[x] = i;
dfs(x + , cl);
}
col[x] = cl + ;
dfs(x + , cl + );
}
int main()
{
scanf("%d", &s);
pw[] = ;
for (R int i = ; i <= s; ++i)
{
scanf("%s", str); pw[i] = pw[i - ] * ;
len = strlen(str);
for (n = ; n <= ; ++n) if (n * (n - ) == len * ) break;
for (R int j = ; j < len; ++j) b[i][j] = (str[j] == '');
}
// for (R int i = 1; i <= s; ++i) {for (R int j = 0; j < len; ++j) printf("%d", b[i][j] == 1); puts("");}
S[][] = ;
for (R int i = ; i <= n; ++i)
{
S[i][] = ;
for (R int j = ; j <= i; ++j)
S[i][j] = S[i - ][j - ] + j * S[i - ][j];
}
f[] = ;
for (R int i = ; i <= n; ++i)
{
for (R int j = i - ; j; --j)
f[i] -= S[i][j] * f[j];
// printf("%lld\n", f[i]);
}
R int cnt = ;
for (R int i = ; i <= n; ++i)
for (R int j = i + ; j <= n; ++j)
id[i][j] = id[j][i] = cnt++;
dfs(, );
printf("%lld\n", ans);
return ;
}
/*
3
111
111
111
*/

最新文章

  1. CSharpGL(7)对VAO和VBO的封装
  2. jQuery -原生 如何互转
  3. react + iscroll5 实现完美 下拉刷新,上拉加载
  4. 前端见微知著AngularJS备忘篇:温故而知新,可以为师矣
  5. U-boot的环境变量值得注意的有两个: bootcmd 和bootargs
  6. css margin 参数
  7. 初始化 Gradle 工程目录(转自: 隔叶黄莺 Unmi Blog)
  8. easyui表单插件-包括日期时控件-列表
  9. [shell基础]——split命令
  10. 【转】IOS --- OC与Swift混编
  11. AWS--EC2基本概念
  12. 优化SQLServer数据库加快查询速度
  13. 蓝桥杯-买不到的数目-java
  14. QQ数据库管理
  15. 深入理解SpringIOC容器
  16. vue常用属性
  17. Java反射(一眼就看会)
  18. Mac OS X Git安装教程
  19. MyEclipse Web项目调试
  20. xa

热门文章

  1. MGR+Consul+ProxySQL
  2. error: [Errno 13] Permission denied: &#39;/usr/local/lib/处理方法
  3. Jmeter之cookie登录
  4. Linux更改ext4根目录文件系统大小
  5. dev listbox使用
  6. 使用modle1(jsp+javabeans)及cookie技术实现商品展示和浏览记录
  7. java面试6
  8. Mac EI 10.11.3 MySQL5.7.11 .dmg 安装(便捷设置,密码重置,卸载)
  9. https和http的post发送总结
  10. 【3】Zookeeper中的角色