D. Meta-set(组合数学)

Problem - D - Codeforces

D. Meta-set(组合数学)_第1张图片

 

你喜欢纸牌棋盘游戏“集合”。每张牌包含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
#include
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
typedef pair PII;
map 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 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();
    }
}

你可能感兴趣的:(java,开发语言)