CF985G Team Players

CF985G Team Players

Luogu CF985C

题面翻译

\(n\) 个点,编号依次为 \(0,1....n-1\)

如果一个三元组 \((i,j,k)~(i<j<k)\) 两两没有边相连,那么它的贡献为 \(A*i+B*j+C*k\)

求出所有三元组的贡献和,答案对 \(2^{64}\) 取模。

题目描述

There are $ n $ players numbered from \(0\) to \(n-1\) with ranks. The \(i\) -th player has rank \(i\) .

Players can form teams: the team should consist of three players and no pair of players in the team should have a conflict. The rank of the team is calculated using the following algorithm: let \(i\) , \(j\) , \(k\) be the ranks of players in the team and \(i < j < k\) , then the rank of the team is equal to \(A \cdot i + B \cdot j + C \cdot k\) .

You are given information about the pairs of players who have a conflict. Calculate the total sum of ranks over all possible valid teams modulo \(2^{64}\) .

输入格式

The first line contains two space-separated integers \(n\) and \(m\) ( \(3 \le n \le 2 \cdot 10^5\) , \(0 \le m \le 2 \cdot 10^5\) ) — the number of players and the number of conflicting pairs.

The second line contains three space-separated integers \(A\) , \(B\) and \(C\) ( \(1 \le A, B, C \le 10^6\) ) — coefficients for team rank calculation.

Each of the next \(m\) lines contains two space-separated integers \(u_i\) and \(v_i\) ( \(0 \le u_i, v_i < n, u_i \neq v_i\) ) — pair of conflicting players.

It's guaranteed that each unordered pair of players appears in the input file no more than once.

输出格式

Print single integer — the total sum of ranks over all possible teams modulo \(2^{64}\) .

样例 #1

样例输入 #1

4 0
2 3 4

样例输出 #1

64

样例 #2

样例输入 #2

4 1
2 3 4
1 0

样例输出 #2

38

样例 #3

样例输入 #3

6 4
1 5 3
0 3
3 5
5 4
4 3

样例输出 #3

164

提示

In the first example all \(4\) teams are valid, i.e. triples: {0, 1, 2}, {0, 1, 3}, {0, 2, 3} {1, 2, 3}.

In the second example teams are following: {0, 2, 3}, {1, 2, 3}.

In the third example teams are following: {0, 1, 2}, {0, 1, 4}, {0, 1, 5}, {0, 2, 4}, {0, 2, 5}, {1, 2, 3}, {1, 2, 4}, {1, 2, 5}.

Solution

两两不连边不好计算,考虑容斥,分为所有三元组、至少有一条边相连的、至少有两条边相连的、至少有三条边相连的。

第四种很好计算,直接套三元环计数板子即可,考虑剩余的如何计算。

由于笔者习惯,以下所有节点编号改为 \([1,n]\),因此在计算对答案的贡献的时候会 \(-1\)

  • 所有三元组 \((x,y,z)\)

    枚举 \(i\in[1,n]\),分讨 \(i\) 在三元组中的位置:

    • \(x=i\):此时 \(y,z\) 只需要满足大于 \(x\),因此对答案贡献 \(A\cdot\dfrac{(n-i)(n-i-1)}2\cdot (i-1)\)
    • \(y=i\):此时 \(x\in[1,y)\)\(z\in(y,n]\),因此对答案贡献 \(B\cdot (i-1)(n-i)(i-1)\)
    • \(z=i\):此时 \(x,y\) 只需要满足小于 \(z\),因此对答案贡献 \(C\cdot\dfrac{(i-1)(i-2)}2\cdot(i-1)\)
  • 至少有一条边相连:

    枚举所有边 \(u\leftrightarrow v\),不妨设 \(u<v\),考虑分讨第三个元素 \(t\)\(u,v\) 的大小关系:

    • \(x=u\):此时只需要 \(t>x\),因此对答案贡献为 \(A\cdot(u-1)(n-u-1)\)
    • \(y=u\):此时只需要 \(t<x\),因此对答案贡献为 \(B\cdot(u-1)(u-1)\)
    • \(y=v\):此时只需要 \(t>y\),因此对答案贡献为 \(B\cdot(v-1)(n-v)\)
    • \(z=v\):此时只需要 \(t<y\),因此对答案贡献为 \(C\cdot(v-1)(v-2)\)
    • \(x=t\):此时 \(t\in[1,u)\),利用等差数列求和公式得到贡献为 \(A\cdot \dfrac{(u-1)(u-2)}2\)
    • \(y=t\):此时 \(t\in(u,v)\),同理得到贡献为 \(B\cdot\dfrac{(u+v-2)(v-u-1)}2\)
    • \(z=t\):此时 \(t\in(v,n]\),贡献为 \(C\cdot\dfrac{(n+v-1)(n-v)}2\)
  • 至少有两条边相连:

    考虑枚举每个点的出边,先将出边按照到达节点的编号排序。设当前枚举的节点是 \(u\),到达的节点为 \(v\),在 \(u\) 的所有可到达节点中排名第 \(i\)\(u\) 所有可到达的节点个数为 \(tn\)。分讨一下 \(u,v\) 的大小关系,设第三个元素的编号为 \(t\)

    • \(v<u\)

      • \(t<v\),则 \(v\) 对答案贡献 \(A\cdot (v-1)(tn-i-1)\)
      • \(t>v\),则 \(v\) 对答案贡献 \(B\cdot(v-1)(i-1)\)
    • \(v > u\)

      • \(t<v\),则 \(v\) 对答案贡献 \(C\cdot(v-1)(i-2)\)
      • \(t>v\),则 \(v\) 对答案贡献 \(B\cdot(v-1)(tn-i)\)

    对于 \(u\) 对答案的贡献,也进行分讨:

    • \(x=u\):此时为 \(t,v>u\),贡献为 \(A\cdot\dfrac{(tn-i)(tn-i-1)}2\cdot(u-1)\)
    • \(y=u\):此时 \(t,v\) 分居 \(u\) 两侧,贡献为 \(B\cdot(tn-i)(i-1)\cdot(u-1)\)
    • \(z=u\):此时 \(t,v<u\),贡献为 \(C\cdot\dfrac{(i-1)(i-2)}2\cdot(u-1)\)

分讨完了过后将所有情况乘上容斥系数加起来即是答案。

#include<bits/stdc++.h>

using namespace std;
using ui64 = unsigned long long;

int n, m;
ui64 A, B, C;
ui64 ans = 0;
constexpr int _N = 2e5 + 5;
vector<int> oe[_N], ne[_N];
int deg[_N], fr[_N], to[_N];

ui64 GetAns1() {
	ui64 sum = 0;
	
	for (int X = 1; X <= n; ++X)
		for (int Y : ne[X]) {
			int x = min(X, Y), y = max(X, Y);
			sum += A * (x - 1) * (n - x - 1);
			sum += B * (x - 1) * (x - 1);
			sum += B * (y - 1) * (n - y);
			sum += C * (y - 1) * (y - 2);
			sum += A * (x - 1) * (x - 2) / 2;
			sum += B * (y + x - 2) * (y - x - 1) / 2;
			sum += C * (n + y - 1) * (n - y) / 2;
		}
	
	return sum;
}

ui64 GetAns2() {
	ui64 sum = 0;
	
	for (int X = 1; X <= n; ++X) {
		oe[X].emplace_back(X);
		sort(oe[X].begin(), oe[X].end());
		int tn = oe[X].size() - 1;
		
		for (int i = 0; i <= tn; ++i) {
			int Y = oe[X][i];
			
			if (Y != X) {
				if (Y < X) {
					sum += A * (Y - 1) * (tn - i - 1);
					sum += B * (Y - 1) * i;
				} else {
					sum += B * (Y - 1) * (tn - i);
					sum += C * (Y - 1) * (i - 1);
				}
			} else {
				sum += A * (tn - i) * (tn - i - 1) / 2 * (X - 1);
				sum += B * i * (tn - i) * (X - 1);
				sum += C * i * (i - 1) / 2 * (X - 1);
			}
		}
	}
	
	return sum;
}

int vis[_N];

ui64 GetAns3() {
	ui64 sum = 0;
	
	for (int X = 1; X <= n; ++X) {
		for (int Y : ne[X]) vis[Y] = X;
		
		for (int Y : ne[X]) for (int Z : ne[Y]) {
			if (vis[Z] != X) continue;
			
			int t[] = {X, Y, Z};
			sort(t, t + 3);
			sum += (t[0] - 1) * A + (t[1] - 1) * B + (t[2] - 1) * C;
		}
	}
	
	return sum;
}

ui64 GetAll() {
	ui64 sum = 0;
	
	for (int i = 1; i <= n; ++i) {
		sum += A * (n - i) * (n - i - 1) / 2 * (i - 1);
		sum += B * (i - 1) * (n - i) * (i - 1);
		sum += C * (i - 1) * (i - 2) / 2 * (i - 1);
	}
	
	return sum;
}

signed main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n >> m >> A >> B >> C;
	
	for (int i = 1; i <= m; ++i) {
		cin >> fr[i] >> to[i]; ++fr[i], ++to[i];
		oe[fr[i]].emplace_back(to[i]);
		oe[to[i]].emplace_back(fr[i]);
		++deg[fr[i]], ++deg[to[i]];
	}
	
	for (int i = 1; i <= m; ++i) {
		int x = fr[i], y = to[i];
		
		if (deg[x] > deg[y] || (deg[x] == deg[y] && x > y)) swap(x, y);
		
		ne[x].emplace_back(y);
	}
	
	ui64 all = 0, sum = 0;
	all = GetAll();
	sum = GetAns1() - GetAns2() + GetAns3();
	cout << all - sum << '\n';
}
posted @ 2023-03-08 21:55  Hanx16Msgr  阅读(30)  评论(0编辑  收藏  举报