codeforces 1598 D.Training Session(组合计数+思维)

题目链接
题意:
\(n\)个问题,每个问题有两个属性\(a\)\(b\),求任意选取三个问题满足属性\(a\)互不相同,或者\(b\)互不相同的方案数。

思路:
不满足的必符合以下情况之一:
(1)选取的三个问题中属性\(a\)有两个相同或全相同。
(2)选取的三个问题中属性\(b\)有两个相同或全相同。
故不满足的情况共有三种。
题目说明没有两个问题有相同的\(a\)\(b\)属性。所以当三个问题\(a\)属性全相同时,\(b\)属性必互不相同,\(b\)属性全相同时同理。
所以不满足的情况只有选取的三个问题中恰有两个问题\(a\)相同,\(b\)相同。

code:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <deque>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
// #include <unordered_map>

#define fi first
#define se second
#define pb push_back
// #define endl "\n"
#define debug(x) cout << #x << ":" << x << endl;
#define bug cout << "********" << endl;
#define all(x) x.begin(), x.end()
#define lowbit(x) x & -x
#define fin(x) freopen(x, "r", stdin)
#define fout(x) freopen(x, "w", stdout)
#define ull unsigned long long
#define ll long long 

const double eps = 1e-15;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const int mod =  998244353;
const int maxn = 1e6 + 10;

using namespace std;

int ca[maxn], cb[maxn], a, b, n;
vector<int> v[maxn];

void solve(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)ca[i] = cb[i] = 0, v[i].clear();
    for(int i = 1; i <= n; i ++){
        scanf("%d%d", &a, &b);
        ca[a] ++, cb[b] ++;
        v[a].pb(b);
    }
    ll ans = 1ll * n * (n - 1) * (n - 2) / 6;
    for(int i = 1; i <= n; i ++){
        for(int j = 0; j < v[i].size(); j ++){
            ans -= 1ll * (ca[i] - 1) * (cb[v[i][j]] - 1);
        }
    }
    cout << ans << endl;
}

int main(){
    int t;
    scanf("%d", &t);
    while(t --)solve();
    return 0;
}
posted @ 2021-10-13 00:21  lniiwuw  阅读(159)  评论(0)    收藏  举报