Problem - D - Codeforces
你喜欢纸牌棋盘游戏“集合”。每张牌包含k个特征,每个特征都等于集合{0,1,2}中的一个值。这副牌包含所有可能的纸牌变体,也就是说,总共有3k张不同的纸牌。
如果三张牌的某个特征与这三张牌相同或两两不同,则称其为好(good)。如果所有k个特征都对3张牌有利,则称这3张牌为一个集合(set)。
例如,牌(0,0,0)、(0,2,1)和(0,1,2)是一个集合,但牌(0,2,2)、(2,1,2)和(1,2,0)不是一个集合,例如,最后一个特征就不太好。
一组5张牌被称为元集合(meta-set),如果它们之间有严格意义上的多于一个集合。给定n张不同的牌,有多少个元集?
输入
第一行输入包含两个整数n和k(1≤n≤103,1≤k≤20)——一张桌子上的牌的数量和牌的特征数量。卡片的描述在接下来的n行中。
描述一张卡片的每一行包含k个整数ci,1,ci,2,…,ci,k(0≤ci,j≤2)-卡片特征。它保证所有的牌都是不同的。
输出
输出一个整数——元集的数量。
例子
inputCopy
8 4
0 0 0 0
0 0 0 1
0 0 0 2
0 0 1 0
0 0 2 0
0 1 0 0
1 0 0 0
2 2 0 0
outputCopy
1
inputCopy
7 4
0 0 0 0
0 0 0 1
0 0 0 2
0 0 1 0
0 0 2 0
0 1 0 0
0 2 0 0
outputCopy
3.
inputCopy
9 - 2
0 0
0 1
0 2
1 0
1
1 2
2 0
2 1
2 - 2
outputCopy
54
inputCopy
20 4
0 2 0 0
0 2 2 2
0 2 2 1
0 2 0 1
1 2 2 0
1 2 1 0
1 2 2 1
1 2 0 1
1 1 2 2
1 1 0 2
1 1 2 1
1 1 1 1
2 1 2 0
2 1 1 2
2 1 2 1
2 1 1 1
0 1 1 2
0 0 1 0
2 2 0 0
2 0 0 2
outputCopy
0
请注意
下面画出表示前四个特征的扑克牌。第一个特征表示一张牌上有多少个对象:1、2、3。第二个是颜色:红色,绿色,紫色。第三种是形状:椭圆形、菱形、曲线型。第四种是填充:开口,条纹,实心。
你可以在下面看到前三个测试。对于前两个测试,元集被突出显示。
在第一个测试中,唯一的元集是5张牌(0000,0001,0002,0010,0020)。其中的集合是三元组(0000,0001,0002)和(0000,0010,0020)。此外,集合是三元组(0100,1000,2200),它不属于任何元集。
在第二个测试中,以下5张卡片组成的组是元集(0000,0001,0002,0010,0020)、(0000,0001,0002,0100,0200)、(0000,0010,0020,0100,0200)。
在第三个测试中,有54个元集。
题解:
一个由5张卡片构成的五元组可以被称为元集合,当且仅当你能从这5张卡片里面找出至少2个好集合。
我们可以发现其中一个元素必定是两个集合的共有部分,
所以我们每次枚举两个集合,找符合这两个集合的应该长什么样,记录下来
最后遍历n个卡片,看我们刚才构造的是否存在,如果存在,肯定是会有x个集合符合,但是我们求的是元集合,这张卡存在x的好集合中,所有有x*(x-1)/2种
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
#include<string>
#include<map>
#define int long long
using namespace std;
typedef pair<int,int> PII;
map<int,int> f;
string a[3000];
void solve()
{
int n,k;
cin >>n >>k;
for(int i = 1;i <= n;i++)
{
for(int j = 0;j < k;j++)
{
char x;
cin >> x;
a[i] += x;
}
}
map<string,int> cnt;
for(int i = 1;i < n;i++)
{
for(int j = i +1;j <= n;j++)
{
string t;
for(int p = 0;p < k;p++)
{
t += ('6' - '0' - (a[i][p]-'0')-(a[j][p]-'0'))%3+'0';
}
cnt[t]++;
}
}
int ans = 0;
for(int i = 1;i <= n;i++)
{
int t = cnt[a[i]];
ans += t*(t-1)/2;
}
cout << ans;
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}