题解:P11777 [COTS 2013] 集合求解 / BOMBONI
Lucyna_Kushinada · · 题解
P11777 [COTS 2013] 集合求解 / BOMBONI
题意
存在若干个集合(集合数量未知,不存在空集),给定
定义全集
- 若集合
A 存在,那么\complement_UA 也存在。 - 对于当前的两个集合
A,B ,集合C=A \cup B 也存在。
求出最小的集合数量,把它对
题解
知识点:集合。
启发:
- 没思路的话先打暴力找规律。
又要求最小,又要计数,仔细思考可以发现问的是所给的集合能通过题中操作产生多少种不同的集合,纯纯的计数题。
结论是过了之后才会证的。
打暴力找规律,发现答案都是形如
根据高中集合知识可以知道
所以虽然题目没给出集合交的操作,但也是可以只用补集和集合并凑出来的。
设
这样题意便转化为了用
考虑把
考虑怎样的集合,满足其任意真子集不能由
这个过程可以用哈希实现。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()
#define N 202505
#define int unsigned long long
const int mod=1e9+9;
int n,m,ha[N];
inline int qpow(int a,int b){
int ans=1;
while(b){
if(b&1){
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
rep(i,1,m){
int k,x;
cin>>k;
while(k--){
cin>>x;
ha[x]=ha[x]*131+i;
}
}
vector<int>tmp;
rep(i,1,n){
tmp.pb(ha[i]);
}
sort(all(tmp));
tmp.erase(unique(all(tmp)),ed(tmp));
cout<<(qpow(2,sz(tmp))-1+mod)%mod;
return 0;
}