L2005 集合相似度 模拟;set

L2-005 集合相似度 (25 分)


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


输入格式

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

之后一行给出一个正整数\(K\)\(\leqslant 2000\)),随后\(K\)行,每行对应一对需要计算相似度的集合的编号(集合从\(1\)\(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%

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB



Solution

思路来自 kimsimple 的L2-005. 集合相似度

1.发现集合内元素范围为\([0,10^9]\),包含重复元素,并且重复元素本身不做出贡献,故考虑使用STL中的set集合;

2.由于\(N\)很小,甚至\(N*N<K\),故考虑直接预处理每两个集合之间的相似度;

3.对于\(N_c\),即为两个set集合都有的元素个数;对于\(N_t\),即为两个set集合总共的元素个数;


std.cpp

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int N=55;
int n,k;
set<int>s[N];
double ans[N][N];
double work(int x,int y){
	double Nc=0,Nt=s[y].size();
	for(auto it=s[x].begin();it!=s[x].end();++it)
		if(s[y].find(*it)==s[y].end()) ++Nt;
		else ++Nc;
	return Nc/Nt*100.0;
}
int main(){
	scanf("%d",&n);
	for(int m,i=1;i<=n;++i){
		scanf("%d",&m);
		for(int x,j=1;j<=m;++j){
			scanf("%d",&x);
			s[i].insert(x);
		}
	}
	for(int i=1;i<n;++i)
		for(int j=i+1;j<=n;++j)
			ans[i][j]=ans[j][i]=work(i,j);
	scanf("%d",&k);
	for(int x,y,i=1;i<=k;++i){
		scanf("%d %d",&x,&y);
		printf("%.2lf%%\n",ans[x][y]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Potrem/p/L2_005.html