题目链接
题目
Monocarp是伯兰州立大学编程团队的教练。他决定为他的团队的培训课程编写一个问题集。
Monocarp有n个问题,他的学生还没有见过。第i个问题有一个主题ai(从1到n的整数)和一个难度bi(从1到n的整数)。所有的问题都是不同的,也就是说,没有两个任务同时具有相同的主题和难度。
Monocarp决定从n个问题中选择3个问题作为问题集。问题应至少满足以下两个条件之一(可能同时满足):
三个选定问题的主题都不同;
所有三个选定问题的难度都不同。
您的任务是确定为问题集选择三个问题的方法数。
思路
题目要找的要满足两个条件之一的,这不好找我们选择用全集减去不满足条件的,不满足条件就是a和他相同,b也和他相同,题目说了没有两个完全相同的任务,所以a不同要挑一个任务,b不同要挑一个任务刚好凑出三个任务,然后遍历一遍,a和他相同乘上b和他相同,把这些减去就是答案了。配合代码理解。
ac代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 10;
map<int,int> ma,mb;
int a[maxn],b[maxn];
int main(){
int t; scanf("%d",&t);
while(t --){
int n; scanf("%d",&n);
for(int i = 1; i <= n; i ++){
scanf("%d %d",&a[i],&b[i]);
ma[a[i]] ++;
mb[b[i]] ++;
}
ll ans = 1ll*n * (n - 1) * (n - 2) / 6;
for(int i = 1; i <= n;i ++){
// 其他与a相同的有 ma[a[i]] - 1个与b相同的有 mb[b[i]] - 1
// 组合一下就是 (ma[a[i]] - 1) * (mb[b[i]] - 1)
ans = ans - 1ll * (ma[a[i]] - 1) * (mb[b[i]] - 1);
}
printf("%lld\n",ans);
ma.clear();
mb.clear();
}
return 0;
}