Educational Codeforces Round 115 (Rated for Div. 2) D. Training Session

传送门

题意:

给你n个题,每个题都有一个主题和一个难度,输入保证同一个主题下不会有相同难度的题出现,现选择三个题组成一个题集,问你满足以下至少一个条件的选择有多少种:1.所选择的三个题目主题互不相同。2.所选择的三个题难度互不相同。

思路:

直接算出所有方案数的难度过大,于是走反面,用总的选择数-非法的选择数。
对于此题的输入,我们可以建立邻接矩阵,并将每一种难度的题的数目装入桶中。
遍历所有的问题,对于问题 a ( i , j ) a(i,j) a(i,j),i表示主题,j表示难度,一定包含问题a的非法组合的数目为:
( i 主 题 的 问 题 数 目 − 1 ) ∗ ( j 难 度 的 问 题 数 目 − 1 ) (i主题的问题数目-1)*(j难度的问题数目-1) i1j1
C n 3 C_n^3 Cn3减去这些非法组合就是答案。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll vis[200010];
ll d[200010];
vector<ll>a[200010];

int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
	{
    
    
		ll n;
		cin>>n;
		for(int i = 1; i <= n; i++)
		{
    
    
			ll num,leve;
			scanf("%lld%lld",&num,&leve);
			a[num].push_back(leve);
			vis[leve]++;
		}
		int cnt = 0;
		ll ans = n*(n-1)*(n-2)/6;
		for(int i = 1; i <= n; i++)
		{
    
    
			if(a[i].size())d[++cnt] = i;
		}
		ll k = 0;
		for(int i = 1; i <= cnt; i++)
		{
    
    
			k = 0;
			for(int j = 0; j < a[d[i]].size(); j++)
			{
    
    
				k += (vis[a[d[i]][j]]-1)*(a[d[i]].size()-1);
			}
			ans-=k;
		}
		printf("%lld\n",ans);
		for(int i = 1; i <= n; i++)a[i].clear(),d[i] = 0,vis[i] = 0;
	}
}


猜你喜欢

转载自blog.csdn.net/p15008340649/article/details/120733618