ural 1932 The Secret of Identifier 容斥

时间:2021-12-18 15:20:02

主题链接:点击打开链接

stl+容斥

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
#include <set>
using namespace std;
#define N 65540
#define ll __int64
ll n;
ll a[N][4], mul[4]={1,16,256,4096};
ll h[N];
vector<ll>G[N];
set<ll>myset;
set<ll>::iterator p;
ll find1(ll x){ //设除了x位。其它3位同样
myset.clear();
for(ll i = 0; i < n; i++){
ll now = 0;
for(ll j = 0; j < 4; j++)if(j!=x)
now += a[i][j];
G[now].push_back(i);
myset.insert(now);
}
ll ans = 0;
for(p = myset.begin(); p!=myset.end(); p++) {
ll siz = G[*p].size();
ans += (siz*(siz-1))>>1;
G[*p].clear();
}
return ans;
} ll find2(ll x,ll y){
myset.clear();
for(ll i = 0; i < n; i++) {
ll now = 0;
for(ll j = 0; j < 4; j++)if(j!=x&&j!=y)
now += a[i][j];
G[now].push_back(i);
myset.insert(now);
}
ll ans = 0;
for(p = myset.begin(); p!=myset.end(); p++) {
ll siz = G[*p].size();
ans += (siz*(siz-1))>>1;
G[*p].clear();
}
return ans;
}
ll find3(ll x){
myset.clear();
for(ll i = 0; i < n; i++){
ll now = 0;
now += a[i][x];
G[now].push_back(i);
myset.insert(now);
}
ll ans = 0;
for(p = myset.begin(); p!=myset.end(); p++) {
ll siz = G[*p].size();
ans += (siz*(siz-1))>>1;
G[*p].clear();
}
return ans;
}
int main(){
ll i,j;
for(ll i = 0; i < N; i++)G[i].clear();
while(cin>>n) {
for(i=0;i<n;i++)
{
char s[10]; scanf("%s",s);
for(j=0;j<4;j++) {
a[i][j] = ('0'<=s[j]&&s[j]<='9')?s[j]-'0':s[j]-'a'+10;
a[i][j] *= mul[j];
}
}
ll ans[5] = {0};
ans[1] = find1(0) + find1(1) + find1(2) + find1(3);
ans[2] = find2(0,1) + find2(0,2) + find2(0,3) + find2(1,2) + find2(1,3) + find2(2,3) - ans[1]*3;
ans[3] = find3(0) + find3(1) + find3(2) + find3(3) - ans[1]*3 - ans[2]*2;
ll all = (ll) ((n*(n-1))/2);
ans[4] = all - ans[1] - ans[2] - ans[3];
cout<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<" "<<ans[4]<<endl; }
return 0;
}
/*
4
abcd
abca
abce
abcf
10
0000
1111
2222
3333
4444
5555
6666
7777
8888
9999 */

版权声明:本文博主原创文章,博客,未经同意不得转载。