https://www.luogu.org/problemnew/show/P5123
题意:n头牛,每头牛有5个喜欢的颜色,两头牛有相同的喜欢的颜色则称这两头牛和♂谐,问不和♂谐的牛的对数。
思路:①容斥原理,对于没一头牛喜欢的颜色,枚举子集,用string+特殊符号分隔来判重。nlogn,大常数
②bitset暴力,n^2logn,小常数
容斥:
#include<bits/stdc++.h>
using namespace std;
#define maxn 100000+100
#define ll long long
int n,a[10],ans;
map<string,int> num;
string get_str(int n)
{
string str;
while(n)
{
str+=n%10+'0';
n/=10;
}
reverse(str.begin(),str.end());
return str;
}
int main()
{
// freopen("input.in","r",stdin);
cin>>n;
for(int c=1;c<=n;c++)
{
for(int i=0;i<5;i++)scanf("%d",&a[i]);
sort(a,a+5);
for(int s=1;s<(1<<5);s++)
{
string str;
int cnt=0;
for(int j=0;j<5;j++)if(s&(1<<j))
{
cnt++;
str+="#"+get_str(a[j]);
}
if(cnt&1)ans+=num[str],num[str]++;
else ans-=num[str],num[str]++;
}
}
cout<<(ll)n*(n-1)/2-ans<<endl;
return 0;
}
bitset:
#include<bits/stdc++.h>
using namespace std;
#define maxn 50000+100
int n,a[maxn][6];
map<int,bitset<maxn> >mp;
int main()
{
//freopen("input.in","r",stdin);
cin>>n;
for(int i=1;i<=n;i++)for(int j=1;j<=5;j++)
{
scanf("%d",&a[i][j]);
mp[a[i][j]].set(i);
}
bitset<maxn> p;
long long ans=0;
for(int i=1;i<=n;i++)
{
p.reset();
for(int j=1;j<=5;j++)p|=mp[a[i][j]];
ans+=n-p.count();
}
cout<<ans/2<<endl;
return 0;
}