题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671

考虑计算不是连通图的方案,乘上容斥系数来进行容斥。

可以枚举子集划分(复杂度是O(Bell))。就是 dfs ,记录已经有了几个集合,枚举当前元素放在哪个集合里(给它标一个 id )或者当前元素自己开一个集合。

然后就有了限制:不同点集之间不能有边。本来想限制同一点集必须是连通的,但不好限制,所以就不限制了,把这部分的影响算在容斥系数里。

如果限制不同点集之间不能有边,可以考虑高斯消元。有 k 条边有限制的话,就写出 k 个方程,解出自由元的个数 d ,2d 就可以加入答案。

不过线性基更好写。https://www.cnblogs.com/ljh2000-jump/p/5869991.html

在这道题里,可以算每个图的 nw 值, nw 的第 i 位是1表示第 i 条边限制不能选,而且这个图有第 i 条边;其余情况的话这个图选不选对于第 i 条边是否合法没有影响(也可以是第 i 条边没有限制,所以其合法性自然不会受到任何图选不选的影响),第 i 位上的值就是 0 。这个 nw 只要把 “有限制的边的位是1” 的那个 long long 和 “这个图有的边的位是1” 的那个 long long & 一下就行了。

  然后合法的子集选取方案需要满足选中的图的 nw 异或起来是0。所以对这些 nw 求一个线性基,设线性基大小为 k 、一共 m 个图,则方案数为 2m-k ,因为不在线性基里的图可以任意选,选好它们后异或出来的结果可以通过线性基里的唯一一种选法来调成0。

这样就求出了 “至少有 i 个连通块” 的方案数 w[ i ] 。考虑怎么用它求出 “恰好有 i 个连通块” 的方案数 g[ i ] 。

设容斥系数为 f[ i ] 。统计答案的时候,有 \( ans=\sum\limits_{i=0}^{n}w[i]*f[i] \)

对于 g[ m ] 来说,在 w[ i ] 里包含了 S( m,i ) 个 g[ m ] 。所以 g[ m ] 会被加到答案里 \( \sum\limits_{i=0}^{n}S(m,i)*f[i] \) 次。

现在想要的效果是选取了合适的 f[  ] ,使得求好的 ans 里只包含了 1 个 g[ 1 ] 。

即:  \( \sum\limits_{i=0}^{n}S(m,i)*f[i] = [ m=1 ] \)

设 \( h(m) = [ m=1 ] \) ,则 \( h[m]=\sum\limits_{i=0}^{n}S(m,i)*f[i] \)

因为 S( i , j ) = 0 ( j>i ) ,所以也就是 \( h[m]=\sum\limits_{i=0}^{m}S(m,i)*f[i] \)

这样就是斯特林反演的形式了。于是有 \( f[m]=\sum\limits_{i=0}^{m}(-1)^{m-i}*s(m,i)*h[i] \)

只有 i=1 时 h 的值是1,所以就是 \( f[m]=(-1)^{m-1}*(m-1)! \)   (\( s(m,i)=\frac{m!}{m}=(m-1)! \))

这样就得到了容斥系数,就可以统计答案啦!

之所以这里的容斥系数不是那种 (-1)k 了,是因为那种系数适用于 “至少一个连通块” = “恰好一个连通块”+“恰好两个连通块+ ...  ,而这里是:“至少一个连通块” = “恰好一个连通块 * S(1,1)”+“恰好两个连通块 * S(2,1)” + ... 。

注意到处开 long long 。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int N=,M=,K=;
int n,m,f[K],id[K];
ll ans,bin[N],b[N],base[M];
void init()
{
scanf("%d",&m); char ch[M];
scanf("%s",ch); int len=strlen(ch);
n=(+sqrt(+*len))/; f[]=;for(int i=;i<=n;i++)f[i]=f[i-]*i;
for(int i=n;i;i--)f[i]=((i-)&?-:)*f[i-]; bin[]=;for(int i=,j=max(m,len-);i<=j;i++)bin[i]=bin[i-]<<;//max(m,len-1) for(int i=;i<len;i++)b[]|=(ch[i]=='')?bin[i]:;
for(int i=;i<=m;i++)
{
scanf("%s",ch);
for(int j=;j<len;j++)b[i]|=(ch[j]=='')?bin[j]:;
}
}
void dfs(int cr,int cnt)
{
if(cr>n)
{
ll t=;int bh=;//ll
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++,bh++)
t|=(id[i]==id[j])?:bin[bh];
int tot=;
for(int k=;k<=bh;k++)base[k]=;//<=bh
for(int i=;i<=m;i++)
{
ll nw=b[i]&t;
for(int k=;k<=bh;k++)//bh
if(nw&bin[k])
{
if(!base[k]){base[k]=nw;tot++;break;}
nw^=base[k];
}
}
ans+=bin[m-tot]*f[cnt];
return;
}
for(int i=;i<=cnt;i++)
id[cr]=i,dfs(cr+,cnt);
id[cr]=cnt+; dfs(cr+,cnt+);
}
int main()
{
init();
dfs(,);
printf("%lld\n",ans);
return ;
}

bzoj 4671 异或图——容斥+斯特林反演+线性基的更多相关文章

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

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

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

    传送门 题意: 给出\(s,s\leq 60\)张图,每张图都有\(n,n\leq 10\)个点. 现在问有多少个图的子集,满足这些图的边"异或"起来后,这张图为连通图. 思路: ...

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

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

  4. BZOJ 4671 异或图 | 线性基 容斥 DFS

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

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

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

  6. [BZOJ 4671]异或图

    Description 题库链接 给定 \(s\) 个结点数相同且为 \(n\) 的图 \(G_1\sim G_s\) ,设 \(S = \{G_1, G_2,\cdots , G_s\}\) ,问 ...

  7. HDU 2841 容斥 或 反演

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

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

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

  9. 【BZOJ】4671: 异或图

    题解 写完之后开始TTTTTTT--懵逼 这道题我们考虑一个东西叫容斥系数啊>< 这个是什么东西呢 也就是\(\sum_{i = 1}^{m}\binom{m}{i}f_{i} = [m ...

随机推荐

  1. C++中虚函数和纯虚函数的区别与总结

    首先:强调一个概念 定义一个函数为虚函数,不代表函数为不被实现的函数. 定义他为虚函数是为了允许用基类的指针来调用子类的这个函数. 定义一个函数为纯虚函数,才代表函数没有被实现. 定义纯虚函数是为了实 ...

  2. maven更换下载镜像源-解决下载慢问题

    Maven是当前流行的项目管理工具,但官方的库在国外经常连不上,连上也下载速度很慢.国内oschina的maven服务器很早之前就关了.今天发现阿里云的一个中央仓库,亲测可用. 1 <mirro ...

  3. redhat6.4 数据包无法到达

    由于redhat在初始化的时候,防火墙设置为icmp-host-prohibited,导致数据包无法到达. 具体iptables(所在目录/etc/sysconfig)如下: # Firewall c ...

  4. T-SQL RIGHT JOIN

    RIGHT JOIN外联接与LEFT JOIN相似.取得右表所有记录,并按过滤条件ON去取得左表的记录,取得这些记录,如遇上没有匹配的列使用NULL填充. 演示数据来源,两张表来自http://www ...

  5. xpath选择器简介及如何使用

    xpath选择器简介及如何使用 一.总结 一句话总结:XPath 的全称是 XML Path Language,即 XML 路径语言,它是一种在结构化文档(比如 XML 和 HTML 文档)中定位信息 ...

  6. 【LABVIEW到C#】3》String的操作之Match Pattern Funtion.vi

    C#实现如下 using System; using System.Collections.Generic; using System.Text; using System.Text.RegularE ...

  7. P3374 【模板】树状数组 1

    树状数组模板题,用cdq分治做 cdq分治: 分:把l到r分成两个区间操作 治:对每个分出来的区间进行操作 但是cdq分治和一般分治不同的是,一般的分治左右两个区间互不干扰,但是cdq分治处理的是区间 ...

  8. CPU高获取其线程ID然后分析

    一.具体步骤 shift+p 按照cpu排序 shift+m按照内存排序 1.查看进程下所有线程 top -H -p  pid  2.将十进制数换成16进制:print "%x/n" ...

  9. 使用display:inline-block产生间隙

    使用display:inline-block产生间隙 一.产生的原因:当初设立标准的不是亚洲而是欧洲,inline元素为了正确显示英文字母如y j g等带有尾巴的,就在底下留空.二.解决办法: 四个d ...

  10. python基础之模块一

    一 time模块 时间表示形式 在Python中,通常有这三种方式来表示时间:时间戳.元组(struct_time).格式化的时间字符串:(1)时间戳(timestamp) :通常来说,时间戳表示的是 ...