CCCC团体程序设计天梯赛 L2-005 集合相似度

记录天梯赛题目合集 跳转查看

题目链接

题目描述

给定两个整数集合,它们的相似度定义为:\(N_c\) /\(N_t\) $ ×100%$。其中 \(N_c\) 是两个集合都有的不相等整数的个数,\(N_t\) 是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。

输入格式
输入第一行给出一个正整数\(N(≤50)\),是集合的个数。随后\(N\)行,每行对应一个集合。每个集合首先给出一个正整数\(M(≤10^4 )\),是集合中元素的个数;然后跟\(M\)\([0,10^9]\)区间内的整数。

之后一行给出一个正整数\(K(≤2000)\),随后\(K\)行,每行对应一对需要计算相似度的集合的编号(集合从\(14到\)N$编号)。数字间以空格分隔。

输出格式
对每一对需要计算的集合,在一行中输出它们的相似度,为保留小数点后\(2\)位的百分比数字。

输入样例

3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3

输出样例

50.00%
33.33%

题目分析

这题最难的是理解题目意思,\(N_c\) 是两个集合都有的整数个数,\(N_t\) 是两个集合合并且去重后的整数个数,比如集合A:{1,2,3,5},集合B:{1,3,6,7},\(N_c\)就是两个集合都有的整数{1,3}的个数2,\(N_t\)就是两个集合合并且去重后{1,2,3,5,6,7}的整数个数6。

明白题目的意思后,解决这题就不难了,只需用到C++的 \(set\)\(unordered\_set\) 去存储集合,当询问两个集合时,遍历访问同时存在两个集合的整数个数和计算两个集合合并且去重的个数就可以了。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

const ll inf = 1e18;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;

int n; 

void solve()
{
	cin >> n;
	vector<unordered_set<int>> a(n + 1);
	for (int i = 1; i <= n; i ++) {
		int m;
		cin >> m;
		while (m --) {
			int x;
			cin >> x;
			a[i].insert(x); // 第i个集合
		}
	}
	
	int k;
	cin >> k;
	while (k --) {
		int x, y;
		cin >> x >> y;
		unordered_set<int> v;
		int cnt = 0, num = a[x].size() + a[y].size();
        // 遍历查询同时存在两个集合的整数个数
		for (auto it : a[x])
			if (a[y].count(it)) cnt ++;
		num -= cnt;
		printf("%.2lf%%\n", 1.0 * cnt / num * 100);
	} 
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr), cout.tie(nullptr);
	
	int T = 1;
//	cin >> T;
	while (T --) solve();
	return 0;
}
posted @ 2025-03-26 21:19  Natural_TLP  阅读(72)  评论(0)    收藏  举报