传送门

题意:

给出\(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\)个自由变量,对于任意一组自由变量的取值,我们都能找到一组唯一的对应的解满足方程。

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

代码如下:

/*
* Author: heyuhhh
* Created Time: 2019/12/17 15:36:21
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 105; int s, n;
char ch[N];
int G[N][N][N];
int a[N];
ll p[64], fac[N];
ll ans; void dfs(int x, int up) {
if(x == n) {
memset(p, 0, sizeof(p));
int c = 0;
for(int k = 1; k <= s; k++) {
ll res = 0;
int tot = 0;
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
if(a[i] != a[j]) res |= ((ll)G[k][i][j] << tot);
++tot;
}
}
for(int i = tot; i >= 0; i--) if(res >> i & 1) {
if(!p[i]) {
++c; p[i] = res;
break;
}
res ^= p[i];
}
}
if(up & 1) ans += fac[up - 1] * (1ll << (s - c));
else ans -= fac[up - 1] * (1ll << (s - c));
return;
}
for(int i = 1; i <= up + 1; i++) {
a[x + 1] = i; dfs(x + 1, max(i, up));
}
} void run(){
fac[0] = 1;
for(int i = 1; i < 12; i++) fac[i] = fac[i - 1] * i;
for(int k = 1; k <= s; k++) {
cin >> (ch + 1);
int len = strlen(ch + 1), cnt = 0;
for(int j = 1; !n; j++) if(j * (j - 1) == 2 * len) n = j;
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
G[k][i][j] = ch[++cnt] - '0';
}
}
}
a[1] = 1;
dfs(1, 1);
cout << ans << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> s) run();
return 0;
}

【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. R语言主成分分析(PCA)

    数据的导入 > data=read.csv('F:/R语言工作空间/pca/data.csv') #数据的导入> > ls(data) #ls()函数列出所有变量 [1] " ...

  2. ajax来获取JWT的token

    AJAX方式获取token需要用

  3. spring源码学习之设计模式(1)单例模式

    众所周知,单例模式分为饿汉式和懒汉式,昨天在看了<spring5核心原理与30个类手写实战>之后才知道饿汉式有很多种写法,分别适用于不同场景,避免反射,线程不安全问题.下面就各种场景.采用 ...

  4. moment.js 默认使用服务器时间

    在前端使用Date对象获取当前时间的时候,该时间是客户端的时间.但是该时间可以被用户修改,所以我们一般情况下并不想要这个时间.如果每一次获取时间的时候都请求一下服务器,那么将会对服务器造成不必要的压力 ...

  5. CCPC Wannafly Winter Camp Div2 部分题解

    Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...

  6. 安卓逆向基础(002)-android虚拟机

    一, android分两种 1.Android 5.0以下(不含5.0) dalvik字节码 为dalvik虚拟机(jit机制) 基于寄存器架构 .dex=>dexopt=>.odex d ...

  7. 《Java数据结构》树形结构

    树形结构是一层次的嵌套结构. 一个树形结构的外层和内层有相似的结构, 所以这种结构多可以递归的表示.经典数据结构中的各种树形图是一种典型的树形结构:一颗树可以简单的表示为根, 左子树, 右子树. 左子 ...

  8. SVN重新定位操作流程

    因服务器其他系统需要SVN原来使用的443端口无法继续使用需要更换,服务器SVN端口已更新为8443,现将个人电脑SVN文件夹路径重新定位流程展示如下: 确定即修改成功!

  9. mac-安装java、安装maven

    首先检查自己的设备是否已经安装了jdk,在cmd终端输入,如已安装出现对应的版本信息,未安装弹出提示窗,官方网址:http://www.oracle.com/technetwork/java/java ...

  10. abp模块化开发之通用树1:基本使用

    一.概述 有些功能在单个项目或多个项目被重复使用,比如:附件,同一个系统中的多个模块都可能使用到,不同项目也有需要.再比如:有无限级分类的树形功能,区域.产品分类.数据字典等.最简单粗暴的办法是直接复 ...