Description
ABC找到N个箱子,箱子里装着一些玩具,一共有M种玩具,编号从1到M,同一种玩具可能出现在多个箱子里。
ABC决定从中选择一些箱子,把这些箱子中的玩具聚集到一起,必须保证每种玩具至少出现一次。
问ABC一共有多少种选择方案。
Input
第一行输入两个整数N和M(1<=N<=1,000,000,1<=M<=20)
接下来N行,每行首先输入Ki(0<=ki<=M),接下来输入Ki个1到M之间互不相同的数,表示玩具的编号。
Output
输出一个整数表示选择方案 mod 1 000 000 007的结果。
Sample Input
输入1:
3 3
3 1 2 3
3 1 2 3
3 1 2 3
输入2:
3 3
1 1
1 2
1 3
输入3:
4 5
2 2 3
2 1 2
4 1 2 3 5
4 1 2 4 5
Sample Output
输出1:
7
输出2:
1
输出3:
6
Data Constraint
50%的数据满足 N<=100,M<=10
70%的数据满足 N<=1000,000,M<=15
100%的数据满足 N<=1000,000,M<=20
Solution
容斥原理。
答案=总方案数-非法方案
非法方案若何求?
我们发现若有一种情况其中有空的位置那么它一定是不可以的,所以对于一些箱子中若有一种或多种玩具都没有,那么这些箱子的所有组合方式都是非法的。
设f[ i ]表示状态为 i 时有多少个箱子中对应的位置没有这些种类的玩具,那么我们就可以算出这f[ i ]个箱子的组合都是非法的。
但是会有重复,当你的状态中只有一种玩具没有,你都将他们减去后,那些状态中有两种玩具没有的状态相当于多减了一次,所以在加回状态中有两种玩具没有的,以此类推。
但是重点是f[ i ]不好求,我们可以反过来想,我们存下读入的状态,然后在任意为0的位上加1,求出所有的方案数后,f[ i ]就相当于是状态 i 取反了,这样有什么好处呢?方便理解吧(当然你也可以减1),因为在我们0的位上加1的过程中就相当于状态数加了一个2的幂,比如0可以更新1,2,3,4...而7可以更新15,31....我们发现可以让一个数先在一个位置上加1,然后再在更新后的数上加2的幂,就类似一个宽搜的过程,其实我们又发现这个过程又很像分治,分治时,我们向两边递归,然后用左半边的来更新相对应的右半边的就能达到这种效果了。比如1,0 1 | 2 3 它可以更新3,然后 0 1 2 3 | 4 5 6 7,1又可以更新5,再用3更新7,这就相当于1更新7,以此类推,就能在O(2^m log 2^m)的时间复杂度内完成了。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000010
#define M 1000000007
#define ll long long
using namespace std;
int n,m,k,x,a[N];
ll ans,f[1048586];
ll ksm(ll k){
if(k<2) return k+1;
ll s=ksm(k>>1);s=s*s%M;
if(k%2==1) return (s<<1)%M;
return s;
}
void dg(int l,int r){
int mid=(l+r)>>1;
if(l==r) return;
dg(l,mid);dg(mid+1,r);
for(int i=0;i<=mid-l;i++){
f[mid+i+1]+=f[l+i];
}
}
void dfs(int x,int s,int t){
if(x>m){
if(!s) return;
if(t%2==1) ans=(ans-(ksm(f[s^((1<<m)-1)])-1)+M)%M;
else ans=(ans+(ksm(f[s^((1<<m)-1)])-1)+M)%M;
return;
}
dfs(x+1,s,t);
dfs(x+1,s+(1<<(x-1)),t+1);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&k);
int s=0;
for(int i=1;i<=k;i++){
scanf("%d",&x);
s+=1<<(x-1);
}
f[s]++;
}
dg(0,(1<<m)-1);
ans=(ksm(n)-1+M)%M;
dfs(1,0,0);
printf("%lld\n",ans);
return 0;
}
作者:zsjzliziyang
QQ:1634151125
转载及修改请注明
本文地址:https://blog.csdn.nehttps://blog.csdn.net/zsjzliziyang/article/details/89525345