【XSY2701】异或图 线性基 容斥原理
2018-01-23 16:04
363 查看
题目描述
定义两个图G1与G2的异或图为一个图G,其中图G的每条边在G1与G2中出现次数和为1。给你m个图,问你这m个图组成的集合有多少个子集的异或图为一个连通图。
n≤10,m≤60
题解
考虑枚举图的子集划分,让被划分到不同子集的点之间没有连边,而在同一个子集里面的点可以连通,可以不连通。可以用高斯消元(线性基)得到满足条件的图的个数。设枚举的子集划分有k个集合,那么容斥系数就是(−1)k−1(k−1)!。并把当前的方案数乘以容斥系数计入答案。
那么容斥系数是怎么来的呢?
记ci为i个集合的容斥系数。对于每一个联通块个数为j的图,对枚举到的联通块个数为i的方案有S(j,i)的贡献。
我们只需要让∑ni=mc(i)S(i,m)=[m=1]就可以了。
可以打表消元消除容斥系数。
时间复杂度:O(Bnn2m),其中Bn是Bell数的第n项。
代码
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; char s[1010]; int n,m; ull a[20][20]; int d[20]; ull ans=0; ull pw[70]; ull fac[70]; ull c[70]; void dfs(int x,int y) { if(x>n) { int i,j,k; for(i=0;i<m;i++) c[i]=0; for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) if(d[i]!=d[j]) { ll s=a[i][j]; for(k=m-1;k>=0;k--) if(s&(1ll<<k)) { if(!c[k]) { c[k]=s; break; } s^=c[k]; } } int num=0; for(i=0;i<m;i++) if(!c[i]) num++; ans+=pw[num]*fac[y-1]*(y&1?1:-1); return; } int i; for(i=1;i<=y;i++) { d[x]=i; dfs(x+1,y); } d[x]=y+1; dfs(x+1,y+1); } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif scanf("%d",&m); int i,j,k; int len; fac[0]=1; pw[0]=1; for(i=1;i<=m;i++) pw[i]=pw[i-1]<<1; for(i=1;i<=m;i++) { scanf("%s",s+1); if(i==1) { len=strlen(s+1); for(j=2;j<=10;j++) if(j*(j-1)/2==len) break; n=j; } int t=0; for(j=1;j<=n;j++) for(k=j+1;k<=n;k++) if(s[++t]=='1') a[j][k]|=1ll<<(i-1); } for(i=1;i<=n;i++) fac[i]=fac[i-1]*i; dfs(1,0); printf("%llu\n",ans); return 0; }
相关文章推荐
- bzoj4671: 异或图【容斥原理+线性基】
- hdu 3949(线性基模版) 异或和中第k小的数
- 【BZOJ4568】幸运数字(SCOI2016)-树上倍增+异或线性基合并
- bzoj 4671: 异或图 容斥+斯特林反演+线性基
- bzoj2115 线性基 异或
- 【jzoj5239】【GDOI2018模拟8.7】【图的异或】【线性基】
- SGU 275 异或线性基
- BZOJ2115 线性基 对于异或环的处理
- hdu 3949(线性基模版) 异或和中第k小的数
- LOJ.114.K大异或和(线性基)
- 【BZOJ2115】【Wc2011】 Xor 线性基 异或最长路
- HDU 3949 异或线性基
- BZOJ2115 线性基 对于异或环的处理
- hdu 3949(线性基模版) 异或和中第k小的数
- bzoj4671 异或图(容斥原理 + 第二类斯特林数 + 高斯消元)
- BZOJ2115 线性基 对于异或环的处理
- hdu 3949(线性基模版) 异或和中第k小的数
- BZOJ 2844 异或线性基(HDU3949 升级版
- BZOJ2115 线性基 对于异或环的处理
- hdu 3949(线性基模版) 异或和中第k小的数