题目描述:
给定两个整数集合,它们的相似度定义为:Nc/Nt×100%。其中Nc是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。
输入格式:
输入第一行给出一个正整数N(≤50),是集合的个数。随后N行,每行对应一个集合。每个集合首先给出一个正整数M(≤104),是集合中元素的个数;然后跟M个[0,109]区间内的整数。
之后一行给出一个正整数K(≤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%
思路:
方法:c++ 标准库 stl 中的 set 数组,双指针。
set 的基本用法是去重并将数组中的元素默认从小到大排序,由于本题研究集合——没有重复元素,但考虑到输入可能有重复的,因此用set来筛选,并重新放入数组 a 中(也可以不放,开个二维set数组,定义可以 set 里面套 set:set<set<int >>st 或者 set<int >st )。
然后针对每次询问,对询问的集合再用个 set 对公共元素的个数进行计数,直接用 st.size() 就可以得出两个集合一共有的不相等整数个数。对于两个集合都有的不相等整数个数可以固定一个集合,用一个指针 j 枚举另一个集合的元素进行判断,由于 set 的性质是默认排序的,所以直接扫一遍就可以。
代码:
#include<bits/stdc++.h>
using namespace std;
int a[55][10005];
int k[55];
set<int >st,su;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >>n;
for(int i = 1;i <= n; ++i){
cin >> k[i];
su.clear();
for(int j = 1;j <= k[i]; ++j){
cin >> a[i][j];
su.insert(a[i][j]);
}
k[i] = su.size();
int uu = 0;
for(auto j = su.begin();j != su.end(); ++j){
a[i][++uu] = *j;
}
}
int T;
cin >>T;
while(T){
st.clear();
int x,y;
cin >> x >>y;
for(int i = 1;i <= k[x];++i){
st.insert(a[x][i]);
}
for(int i = 1;i <= k[y];++i){
st.insert(a[y][i]);
}
int j = 1;
double c=0;
for(int i = 1;i <= k[x];++i){
if(j>k[y]) break;
while(a[y][j]<a[x][i] && j <= k[y])++j;
if(a[y][j]==a[x][i] &&j <= k[y]) c++;
}
printf("%.2lf%\n",(c/(double)st.size())*100);
--T;
}
return 0;
}