New Set

17 篇文章 0 订阅

在这里插入图片描述
述
在这里插入图片描述
在这里插入图片描述

我的思路:因为题目中说是⾄少⼀个 Ai 能分离 (X,Y),我们容斥枚举⼀个 A 的集合
S,然后计算能被 S 中每⼀个分离的 (X,Y) 的个数
如何计算 (X,Y) 的对数呢,根据题⽬条件,A 能分离 (X,Y),当且仅当
X,Y 中⼀个是 A 的⼦集,另⼀个跟 A 没有交
我们在枚举 S 中每个 A 是 X 的超集还是 Y 的超集
然后就可以⼤⼒统计了O(3^m*n),吼啊,20分

正确的:考虑上⾯那个暴⼒最后怎么算答案
假设 S 被分为 U+V,其中 U 中的 A 都是 X 的超集,且与 Y ⽆
交,V 则相反
则可选的 X 是 U 的交的⼦集,且不能与 V 中任何⼀个集合有交
也就是说,如果 a 是 X 的⼀个元素,那么 a 是 U 中所有集合的
元素,且不是 V 中任何⼀个集合的元素
我们可以通过数有⼏个元素满⾜条件来计算 (X,Y)

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define rep2(i,j,k) for(int i=(int)j;i<(int)k;i++)
#define per(i,j,k) for(int i=(int)j;i>=(int)k;i--)
using namespace std;
typedef long long ll;
const int maxn=1e2+5,mod=1e9+7;
int n,m,k,ans;
int binom[maxn][maxn],a[18][maxn],v[maxn],vv[1<<18];
int main()
{
 cin>>n>>m>>k;
 rep(i,0,n)
  rep(j,0,i)
   binom[i][j]=!j?1:(binom[i-1][j-1]+binom[i-1][j])%mod;
 rep2(i,0,m)
 {
  int c;
  cin>>c;
  rep(j,1,c)
  {
   int x;
   cin>>x;
   a[i][x]=1;
  }
 }
 rep2(s,1,1<<m)
 {
  int flag=mod-1;
  rep(i,1,n)
   v[i]=0;
  int cnt=0;
  rep2(i,0,m)
  { 
   if(s>>i&1)
   {
    flag=mod-flag;
    rep(j,1,n)
     if(a[i][j])
      v[j]|=1<<cnt;
    cnt++;
   }
  } 
  sort(v+1,v+n+1);
  rep(i,1,n)
   vv[v[i]]++;
  rep(i,1,n)
  { 
   if((i==1)||(v[i]!=v[i-1]))
   {
    int v1=v[i],v2=((1<<cnt)-1)^v1;
    ans=(ans+1ll*flag*binom[vv[v1]][k]%mod*binom[vv[v2]][k]%mod)%mod;
   }
  } 
  rep(i,1,n)
   vv[v[i]]--;
 }
 cout<<ans<<endl;
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值