Each input file contains one test case. Each case first gives a positive integer N (<=50) which is the total number of sets. Then N lines follow, each gives a set with a positive M (<=104) and followed by M integers in the range [0, 109]. After the input of sets, a positive integer K (<=2000) is given, followed by K lines of queries. Each query gives a pair of set numbers (the sets are numbered from 1 to N). All the numbers in a line are separated by a space.
For each query, print in one line the similarity of the sets, in the percentage form accurate up to 1 decimal place.
3 3 99 87 101 4 87 101 5 87 7 99 101 18 5 135 18 99 2 1 2 1 3
50.0% 33.3%
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
const int N = 50;
int n, k, m;
set<int> s[N];
void solve(int a, int b)
{
set<int>::iterator ia, ib;
int cnt = 0;
ia = s[a].begin();
ib = s[b].begin();
while(1) {
while(ia != s[a].end() && *ia < *ib)
ia++;
while(ib != s[b].end() && *ib < *ia)
ib++;
if(ia == s[a].end() || ib == s[b].end())
break;
if(*ib == *ia) {
cnt++;
ia++;
ib++;
}
}
int sum = s[a].size() + s[b].size() - cnt;
printf("%.1f%%\n", double(cnt*100) / sum);
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &m);
for(int j = 0; j < m; j++) {
int t;
scanf("%d", &t);
s[i].insert(t);
}
}
scanf("%d", &k);
for(int i = 0; i < k; i++) {
int a, b;
scanf("%d%d", &a, &b);
solve(a - 1, b - 1);
}
return 0;
}
import java.util.HashSet;
import java.util.Scanner;
public class No1021 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();// the total number of sets.
HashSet[] sets = new HashSet[n];
for(int i = 0;i<n;i++){
int m = in.nextInt();
sets[i] = new HashSet<Integer>(m);
String[] nums = in.nextLine().split(" ");
for(int j = 1;j<=m;j++)
sets[i].add(Integer.parseInt(nums[j]));
}
int k = in.nextInt();
for(int i = 0;i<k;i++){
int s = in.nextInt()-1;
int e = in.nextInt()-1;
HashSet<Integer> s1 = sets[s];
HashSet<Integer> s2 = sets[e];
int comm = 0;
for (Integer integer : s2) {
if(s1.contains(integer))
comm++;
}
double diff = s1.size()+s2.size()-comm;
System.out.printf("%.1f%%\n",(comm/diff)*100);
}
}
}
#include <iostream>
#include <set>
using namespace std;
set<int> num[55];
int main(){
int n,m,x,k,n1,n2;
cin>>n;
for(int i=1;i<=n;i++){
cin>>m;
for(int j=0;j<m;j++){
cin>>x;
num[i].insert(x); //将元素x加入集合num[i]中
}
}
cin>>k; //k个查询
for(int i=0;i<k;i++){
cin>>n1>>n2; //比较集合num[n1]和num[n2]
int same=0,sum=num[n2].size(); //same为相同元素个数,sum为不同元素个数
for(set<int>::iterator it=num[n1].begin();it!=num[n1].end();it++){ //遍历集合num[n1]
if(num[n2].find(*it)!=num[n2].end()) same++; //若能在num[n2]中找到该元素
else sum++; //若在num[n2]中找不到该元素
}
printf("%.1f%%\n",same*100.0/sum);
}
return 0;
}
#pragma warning (disable:4996)
#include <cstdio>
#include <iostream>
#include <set>
using namespace std;
#define MAX 10000
int N, M, K, cnt = 0;
set<int> s[MAX]; double res[MAX];
int main() {
cin >> N; int tmp;
for (int i = 1; i <= N; ++i) {
cin >> M;
for (int j = 0; j < M; ++j) {
cin >> tmp; s[i].insert(tmp);
}
}
cin >> K; int a, b;
for (int i = 0; i < K; ++i) {
cin >> a >> b;
double nc = 0.0, nt = (double)(s[a].size()) + (double)s[b].size();
for (auto it = s[b].begin(); it != s[b].end(); ++it)
if (s[a].find(*it) != s[a].end())++nc;
res[cnt++] = nc / (nt - nc) * 100;
}
for (int i = 0; i < K; ++i) {
printf("%.1f%%", res[i]);
if (i < K - 1)cout << endl;
}
return 0;
} #include <iostream>
#include <set>
#include <stdio.h>
using namespace std;
int main() {
int set_amount;
cin>>set_amount;
set<int> set_container[set_amount];
for(int i=0; i<set_amount; i++) {
int amount;
cin>>amount;
for(int j=0; j<amount; j++) {
int num;
cin>>num;
set_container[i].insert(num);
}
}
int test;
cin>>test;
for(int i=0; i<test; i++) {
int set1,set2;
cin>>set1>>set2;
int repeat=0;
set<int>::iterator iter1;
for(iter1=set_container[set1-1].begin(); iter1!=set_container[set1-1].end(); iter1++) {
if(set_container[set2-1].count(*iter1)) {
repeat++;
}
}
printf("%.1f%%\n",(float)repeat/(float)(set_container[set1-1].size()+set_container[set2-1].size()-repeat)*100);
}
return 0;
} 多学stl真的是捷径
#include <bits/stdc++.h>
using namespace std;
const int maxn = 55;
set<int> mySet[maxn];
int N, K;
int main()
{
//freopen("in.txt", "r", stdin);
scanf("%d", &N);
int M, read;
for(int i = 1; i <= N; i++) {
scanf("%d", &M);
for(int j = 0; j < M; j++) {
scanf("%d", &read);
mySet[i].insert(read);
}
}
scanf("%d", &K);
int x, y;
for(int i = 0; i < K; i++) {
scanf("%d%d", &x, &y);
int sameNum = 0;
for(set<int>::iterator it = mySet[x].begin(); it != mySet[x].end(); it++) {
if(mySet[y].find(*it) != mySet[y].end()) {
sameNum++;
}
}
int totalNum = mySet[x].size() + mySet[y].size() - sameNum;
printf("%.1f%\n", ((sameNum*1.0)/(totalNum))*100);
}
return 0;
}
import java.util.HashSet;
import java.util.Scanner;
public class SetSimilarity {
private static final int maxn = 55;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
HashSet mySet[] = new HashSet[N];
for(int i = 0; i < N; i++) {
mySet[i] = new HashSet<>();
}
for(int i = 0; i < N; i++) {
int M = scanner.nextInt();
int read;
for(int j = 0; j < M; j++) {
read = scanner.nextInt();
mySet[i].add(read);
}
}
int K = scanner.nextInt();
for(int i = 0; i < K; i++) {
int x = scanner.nextInt()-1;
int y = scanner.nextInt()-1;
int sameNum = 0;
HashSet<Integer> s1 = mySet[x];
HashSet<Integer> s2 = mySet[y];
for(Integer c : s1) {
if(s2.contains(c)) sameNum++;
}
int diff = s1.size() + s2.size() - sameNum;
System.out.printf("%.1f%%\n", (sameNum*1.0/diff)*100);
}
}
}
#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
const int MAXN = 55;
set<int> Set[MAXN];
int N,K;
int main()
{ cin>>N; int M,num; for(int i=1;i<=N;i++) { cin>>M; for(int j=0;j<M;j++) { cin>>num; Set[i].insert(num); } } cin>>K; int x,y; for(int i=0;i<K;i++) { cin>>x>>y; int sameNum = 0; for(set<int>::iterator it=Set[x].begin();it!=Set[x].end();it++) if(Set[y].find(*it) != Set[y].end()) sameNum++; int totalNum = Set[x].size() + Set[y].size() - sameNum; printf("%.1f%%\n",((sameNum*1.0)/totalNum)*100); } return 0;
}
这种题都不敢用cin cout
set的set_intersection()、set_union()也会超时。
#include<bits/stdc++.h>
using namespace std;
set<int> s[51];
void cmp(int a,int b){
int x=s[b].size(),y=0;
for(auto it=s[a].begin();it!=s[a].end();it++){
if(s[b].find(*it)!=s[b].end()){
y++;
}
else x++;
}
printf("%.1f%\n",y*100.0/x);
}
int main() {
int n,m,x;
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&m);
for(int j=0; j<m; j++) {
scanf("%d",&x);
s[i].insert(x);
}
}
int k;
scanf("%d",&k);
for(int i=0;i<k;i++){
int a,b;
scanf("%d %d",&a,&b);
cmp(a,b);
}
return 0;
} 
更多PAT甲级题解--acking-you.github.io
这又是一场关于题目理解的博弈!!!
关键句意:
where Nc is the number of distinct common numbers shared by the two sets, and Nt is the total number of distinct numbers in the two sets.
翻译:
这里的Nc是两个不含相同数字集合的公共数字的数量,Nt是两个不含相同数字集合的数字总量。
所以很简单的直接用STL解决就行了,直接用unordered_set记录给定的集合数据。
无序容器这效率也是yyds!C++11的语法有用白不用!!auto&& : set yyds!!
#include <bits/stdc++.h>
using namespace std;
int N, K;
void solve() {
ios::sync_with_stdio(false);
cin >> N;
unordered_set<int> Set[N + 1];
for (int i = 1; i <= N; i++) {//创建集合
int m;
cin >> m;
while (m--) {
int d;
cin >> d;
Set[i].insert(d);
}
}
cin >> K;
while (K--) {//打印答案
int a, b;
cin >> a >> b;
int nc = 0, nt = Set[b].size();
for (auto &&it :Set[a]) {
if (Set[b].count(it))
nc++;
else
nt++;
}
double ans = (double) nc / nt * 100;
cout << fixed << setprecision(1) << ans << '%' << endl;
}
}
int main() {
solve();
return 0;
}
//set_similarity
#include<iostream>
#include<set>
#include<vector>
#include<iomanip>
using namespace std;
vector<set<int> > list;
void check(int a,int b){
double similar=0;
double same,total;
if(list[b-1].size()<list[a-1].size()){
for(set<int>::iterator it=list[b-1].begin();it!=list[b-1].end();it++){
if(list[a-1].find(*it)!=list[a-1].end())same++;
}
}
else{
for(set<int>::iterator it=list[a-1].begin();it!=list[a-1].end();it++){
if(list[b-1].find(*it)!=list[b-1].end())same++;
}
}
total=list[a-1].size()+list[b-1].size();
similar=same/(total-same);
cout<<fixed<<setprecision(1)<<similar*100<<"%";
}
int main(){
int n;
cin>>n;
vector<set<int> > q(n);
int temp,temp2,temp3;
for(int i=0;i<n;i++){
cin>>temp;
for(int j=0;j<temp;j++){
cin>>temp2;
q[i].insert(temp2);
}
}
cin>>temp;
vector<int> pp1;
vector<int> pp2;
for(int i=0;i<temp;i++){
cin>>temp2>>temp3;
pp1.push_back(temp2);
pp2.push_back(temp3);
}
list=q;
for(int i=0;i<temp;i++){
temp2=pp1[i];temp3=pp2[i];
check(temp2,temp3);if(i!=temp-1)cout<<endl;
}
return 0;
} #include<iostream>
(720)#include<vector>
#include<algorithm>
(831)#include<set>
/*
STL中有直接的集合库,set,其中的元素可用insert添加。
set中的元素默认是按升序排列的。
set不能用下标顺序访问,只能用迭代器遍历访问
求两个集合的交集大小可以直接同时遍历两个集合
求两个集合的并集大小可以用两个集合的大小之和再减去两个集合的交集大小
*/
using namespace std;
const int MAXN = 110;
const int MSET = 51;
int main() {
//freopen("C:\\Users\\47\\Desktop\\1.txt","r",stdin);
int numofSets;
cin >> numofSets;
set<int>Sets[MSET];
for (int i = 0; i < numofSets; i++) {
int numofEachSet, x;
cin >> numofEachSet;
for (int j = 0; j < numofEachSet; j++) {
cin >> x;
Sets[i].insert(x);
}
}
int numofQuery;
cin >> numofQuery;
while (numofQuery--) {
int a, b;//a,b为要查询的两个集合
cin >> a >> b;
int NC = 0, NT = 0;
set<int>::iterator ai = Sets[a - 1].begin();
set<int>::iterator bj = Sets[b - 1].begin();
while (ai!= Sets[a - 1].end()&& bj!=Sets[b - 1].end()) {
if (*ai == *bj) {
NC++;
ai++;
bj++;
}
else if (*ai < *bj) {
ai++;
}
else {
bj++;// 135 236
}
}
NT = Sets[a - 1].size() + Sets[b - 1].size()-NC;
printf("%.1lf%%\n", (NC*1.0/NT*1.0)*100);
}
} N=int(input())
sets=[]
sets=[list(map(int,input().split()))[1:] for i in range(0,N)]
K=int(input())
for i in range(0,K):
a,b=map(int,input().split())
res=len(set(sets[a-1])&set(sets[b-1]))/len(set(sets[a-1])|set(sets[b-1]))
print(format(res,'.1%'))
#include<iostream>
#include<unordered_map>
#include<iomanip>
#include<vector>
using namespace std;
vector<int> arr[51];
unordered_map<int,int> S1[51]; // S1存每个数组单独的数
int T,num,element;
double compare(int num1, int num2) {
if(!S1[num1].size()) { // 没存过就存一下
for(int i = 0; i < arr[num1].size(); ++i) {
element = arr[num1][i];
S1[num1].insert({element,1});
}
}
if(!S1[num2].size()) {
for(int i = 0; i < arr[num2].size(); ++i) {
element = arr[num2][i];
S1[num2].insert({element,1});
}
}
int cnt = 0;
for(auto ite:S1[num1]){ // 找相同的数
if(S1[num2].count(ite.first)){
++cnt;
}
}
double Nt = S1[num1].size()+S1[num2].size()-cnt; // 简单的集合运算
double Nc = cnt;
return Nc/Nt*100;
}
int main() {
ios::sync_with_stdio(false);
cin >> T;
for(int i = 1; i <= T; ++i) {
cin >> num;
for(int j = 0; j < num; ++j) {
cin >> element;
arr[i].push_back(element);
}
}
cin >> T;
int num1,num2;
for(int i = 1; i <= T; ++i) {
cin >> num1 >> num2;
cout << fixed << setprecision(1) << compare(num1,num2) << "%\n";
}
} n = input()
n = int(n)
lst = [None for i in range(n)]
for i in range(n):
tem = set(map(int,input().split()[1:]))
lst[i] = tem
m = input()
m = int(m)
for i in range(m):
a,b = map(int,input().split())
c = lst[a-1]|lst[b-1]
d = lst[a-1]&lst[b-1]
print("%.1f"%(len(d)/len(c)*100)+"%")
思路:如果用set 那就用set的一套东西就好了
set_intersection
求交集合
set_union
求并集
但是排名400+,看来给的算法库不够酷
#include <iostream>
#include <fstream>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
#ifndef debug
ifstream ifile("case.txt");
#define cin ifile
#endif
int main()
{
int n;
while (cin >> n)
{
int k;
set<int> mySet[500];
for (int i = 0; i < n; i++)
{
cin >> k;
for (int j = 0; j < k; j++)
{
int tmp;
cin >> tmp;
mySet[i].insert(tmp);
}
}
// 查询
cin >> n;
int a, b;
for (int i = 0; i < n; i++)
{
cin >> a >> b;
vector<int> plus(mySet[a-1].size() + mySet[b-1].size());
vector<int> minutes(mySet[a - 1].size() + mySet[b - 1].size());
auto it = set_union(mySet[a - 1].begin(), mySet[a - 1].end(), mySet[b - 1].begin(), mySet[b - 1].end(), plus.begin());
plus.resize(it - plus.begin());//重新确定ivec大小
auto iter = set_intersection(mySet[a - 1].begin(), mySet[a - 1].end(), mySet[b - 1].begin(), mySet[b - 1].end(), minutes.begin());
minutes.resize(iter - minutes.begin());//重新确定ivec大小
printf("%.1lf%%\n", minutes.size() * 100.0 / plus.size());
}
}
system("pause");
}
n = int(input())
a = []
for i in range(n):
m = set(map(int,input().split()[1:]))
a.append(m)
k = int(input())
for i in range(k):
q = list(map(int,input().split()))
x, y = q[0]-1, q[1]-1
top = 100.0*len(a[x]&a[y])
down = 1.0*len(a[x]|a[y])
print('%.1f%%' % (top/down))