传送门

题意:

给出\(s,s\leq 60\)张图,每张图都有\(n,n\leq 10\)个点。

现在问有多少个图的子集,满足这些图的边“异或”起来后,这张图为连通图。

思路:

  • 直接考虑判断图的连通不好判断,所以考虑枚举连通块来进行容斥。

  • 定义\(f_i\)表示有\(i\)个连通块的答案,发现连通块这个东西也不好处理,我们只能处理出有多少个连通块,但无法确定每个连通块内部的连通关系。

  • 定义\(g_i\)为至少有\(i\)个连通块的方案数,那么就有关系式:\(\displaystyle g_i=\sum_{j=i}^n \begin{Bmatrix}
    j \\ i
    \end{Bmatrix}f_j\)。至于为什么要乘以一个第二类斯特林数,相当于我们将单个的连通块再进行组合,有不同的组合方式。

  • 此时\(g_i\)就相当于有\(i\)个连通块,内部可连通可不连通的方案数。

  • 因为最终所求为\(f_1\),通过斯特林反演可得:\(\displaystyle f_1=\sum_{i=1}^n(-1)^{i-1}\begin{bmatrix}
    i \\ 1
    \end{bmatrix}g_i\)。那么现在只需要算\(g_i\)即可。

  • 因为点数很少,可以直接枚举子集划分,我们只需要保证最后不同的集合之间没有边相连即可。

  • 当确定了一种子集划分过后,将连接不同集合的边拿出来,将每张图这类边转为二进制插入线性基中,最后的基为\(c\)个,那么答案就为\(2^{s-c}\)。

  • 将答案累加入\(f_i\)即可。

这个题大概就这样做完了,但还有一些小细节,其中,斯特林反演的时候和常见形式稍有不同,但可以通过反转公式证明:

\[\left\{
\begin{aligned}
&\sum_{k=m}^n(-1)^{n-k}\begin{bmatrix}
n \\ k
\end{bmatrix}\begin{Bmatrix}
k \\ m
\end{Bmatrix}=[n=m]\\
&\sum_{k=m}^n(-1)^{k-m}\begin{Bmatrix}
n \\ k
\end{Bmatrix}\begin{bmatrix}
k \\ m
\end{bmatrix}=[n=m]
\end{aligned}
\right.
\]

最后的答案为\(2^{s-c}\)的原因在于,我们相当于来求若干个数异或起来为\(0\)的方案数,每个图用\(x_i\)来表示其最终状态,那么如果有\(c\)个基,说明就有\(s-c\)个自由变量,对于任意一组自由变量的取值,我们都能找到一组唯一的对应的解满足方程。

其实这个本质上就是求解一个异或方程组。

代码如下:

  1. /*
  2. * Author: heyuhhh
  3. * Created Time: 2019/12/17 15:36:21
  4. */
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <cstring>
  8. #include <vector>
  9. #include <cmath>
  10. #include <set>
  11. #include <map>
  12. #include <queue>
  13. #include <iomanip>
  14. #define MP make_pair
  15. #define fi first
  16. #define se second
  17. #define sz(x) (int)(x).size()
  18. #define all(x) (x).begin(), (x).end()
  19. #define INF 0x3f3f3f3f
  20. #define Local
  21. #ifdef Local
  22. #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  23. void err() { std::cout << '\n'; }
  24. template<typename T, typename...Args>
  25. void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  26. #else
  27. #define dbg(...)
  28. #endif
  29. void pt() {std::cout << '\n'; }
  30. template<typename T, typename...Args>
  31. void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
  32. using namespace std;
  33. typedef long long ll;
  34. typedef pair<int, int> pii;
  35. //head
  36. const int N = 105;
  37. int s, n;
  38. char ch[N];
  39. int G[N][N][N];
  40. int a[N];
  41. ll p[64], fac[N];
  42. ll ans;
  43. void dfs(int x, int up) {
  44. if(x == n) {
  45. memset(p, 0, sizeof(p));
  46. int c = 0;
  47. for(int k = 1; k <= s; k++) {
  48. ll res = 0;
  49. int tot = 0;
  50. for(int i = 1; i <= n; i++) {
  51. for(int j = i + 1; j <= n; j++) {
  52. if(a[i] != a[j]) res |= ((ll)G[k][i][j] << tot);
  53. ++tot;
  54. }
  55. }
  56. for(int i = tot; i >= 0; i--) if(res >> i & 1) {
  57. if(!p[i]) {
  58. ++c; p[i] = res;
  59. break;
  60. }
  61. res ^= p[i];
  62. }
  63. }
  64. if(up & 1) ans += fac[up - 1] * (1ll << (s - c));
  65. else ans -= fac[up - 1] * (1ll << (s - c));
  66. return;
  67. }
  68. for(int i = 1; i <= up + 1; i++) {
  69. a[x + 1] = i; dfs(x + 1, max(i, up));
  70. }
  71. }
  72. void run(){
  73. fac[0] = 1;
  74. for(int i = 1; i < 12; i++) fac[i] = fac[i - 1] * i;
  75. for(int k = 1; k <= s; k++) {
  76. cin >> (ch + 1);
  77. int len = strlen(ch + 1), cnt = 0;
  78. for(int j = 1; !n; j++) if(j * (j - 1) == 2 * len) n = j;
  79. for(int i = 1; i <= n; i++) {
  80. for(int j = i + 1; j <= n; j++) {
  81. G[k][i][j] = ch[++cnt] - '0';
  82. }
  83. }
  84. }
  85. a[1] = 1;
  86. dfs(1, 1);
  87. cout << ans << '\n';
  88. }
  89. int main() {
  90. ios::sync_with_stdio(false);
  91. cin.tie(0); cout.tie(0);
  92. cout << fixed << setprecision(20);
  93. while(cin >> s) run();
  94. return 0;
  95. }

【bzoj4671】异或图(容斥+斯特林反演+线性基)的更多相关文章

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671 考虑计算不是连通图的方案,乘上容斥系数来进行容斥. 可以枚举子集划分(复杂度是O(Be ...

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671 首先,考虑容斥,就是设 \( t[i] \) 表示至少有 \( i \) 个连通块的方 ...

  3. BZOJ4671 异或图(容斥+线性基)

    题意 定义两个结点数相同的图 \(G_1\) 与图 \(G_2\) 的异或为一个新的图 \(G\) ,其中如果 \((u, v)\) 在 \(G_1\) 与 \(G_2\) 中的出现次数之和为 \(1 ...

  4. BZOJ4671 异或图 斯特林反演+线性基

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4671 题解 半年前刚学计数的时候对这道题怀着深深的景仰,现在终于可以来做这道题了. 类似于一般 ...

  5. bzoj4671 异或图(斯特林反演,线性基)

    bzoj4671 异或图(斯特林反演,线性基) 祭奠天国的bzoj. 题解时间 首先考虑类似于容斥的东西. 设 $ f_{ i } $ 为至少有 $ i $ 个连通块的方案数, $ g_{ i } $ ...

  6. bzoj4671: 异或图——斯特林反演

    [BZOJ4671]异或图 - xjr01 - 博客园 考虑先算一些限制少的情况 gi表示把n个点的图,划分成i个连通块的方案数 连通块之间不连通很好处理(怎么处理看下边),但是内部必须连通,就很难办 ...

  7. bzoj4671: 异或图

    bzoj4671: 异或图 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 ( ...

  8. HDU 2841 容斥 或 反演

    $n,m <= 1e5$ ,$i<=n$,$j<=m$,求$(i⊥j)$对数 /** @Date : 2017-09-26 23:01:05 * @FileName: HDU 284 ...

  9. 【题解】[HAOI2018]染色(NTT+容斥/二项式反演)

    [题解][HAOI2018]染色(NTT+容斥/二项式反演) 可以直接写出式子: \[ f(x)={m \choose x}n!{(\dfrac 1 {(Sx)!})}^x(m-x)^{n-Sx}\d ...

随机推荐

  1. 最全的linux系统安装教程和排错方法

    第4章 linux信息和系统安装与连接    260 4.1 linux的发展历史    260 4.2 GPL协议,FSF协议    261 4.3 linux系统的安装    261 4.3.1 ...

  2. Robotframework常见问题收集

    一.Robotframework1.7.3控制台乱码处理 1.找到文件C:\Python37\Lib\site-packages\robotide\contrib\testrunner\testrun ...

  3. Java_输入整数求阶乘

    import java.util.Scanner;public class Work4{ public static void main(String[] args){ // 创建Scanner对象 ...

  4. MYSQL-JDBC批量新增-更新-删除

    目录 1 概述 2 开启MYSQL服务端日志 3 深入MYSQL/JDBC批量插入 3.1 从一个例子出发 3.2 JDBC的批量插入操作 3.3 两个常被忽略的问题 3.5 误区 4 MYSQL/J ...

  5. CCF-CSP题解 201803-3 URL映射

    题目要求写一个简易的URL规则和URL地址匹配的程序. 说说我的思路. 将URL规则和地址都截成片段用结构体\(<type, str[]>\)存储.对于URL规则,\(type\)为0代表 ...

  6. poj 2513 Colored Sticks (trie树+并查集+欧拉路)

    Colored Sticks Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 40043   Accepted: 10406 ...

  7. hdu 1028 Ignatius and the Princess III (n的划分)

    Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  8. 记录一次Windows简单构建Dockerfile

    参考文档[https://www.cnblogs.com/GraceSkyer/p/9908984.html] 1]环境说明 操作系统 :win10  ,docker软件:Docker for Win ...

  9. c++-内联函数和函数重载和默认参数和函数指针

    内联函数 C++ 内联函数是通常与类一起使用.如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方. 对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编 ...

  10. leaflet-webpack 入门开发系列六矢量瓦片(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...