12.31 vp Codeforces Global Round 24
A - Doremy's Paint
题意:设c(l,r)为r到l区间不同元素的个数。求a数组中若存在最大可能的r-l-c(l,r),输出l,r
思路:由于1,2,3,3,4,若l = 1, r = 3,r-l-c(l,r) = 0
即区间内不同元素对答案贡献为0,有相同的元素才会有贡献。贪心考虑取到最大贡献即整个数组l = 1, r = n
void solve()
{		
	int n;
	cin >> n;
	for (int i = 1; i <= n; i ++) {
		int x;
		cin >> x;
	}
	cout << 1 << ' ' << n << endl;
}
B - Doremy's Perfect Math Class
题意:给出集合S,在集合中若满足x > y, x - y没在集合中出现。则将x - y加入集合。问集合最多会有多少个元素。
思路:不同的x-y相当于减去因数的过程,设tmp为集合所有元素的最大公因数,答案即为an / tmp
void solve()
{		
	int n;
	cin >> n;
	LL tmp = 0;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
	}
	tmp = a[1];
	
	for (int i = 2; i <= n; i ++){
		tmp = __gcd(tmp, (LL)a[i]);
	}
	
	cout << a[n] / tmp << endl;
}
C - Doremy's City Construction
题意:给出n个顶点,每个顶点都有一个高度,无向图中相连的三个顶点间的高度不能是有顺序的,求图中最大连接的边数是多少
思路:考虑将顶点排序,然后将当前顶点及比自己小的顶点划为一个集合,将大于这个高度的顶点划为一个集合。然后两个集合每个顶点都连一条边,即j * (n - j),取最大值即可。
这样可以保证相连的三个顶点一定是小大小或者大小大的,一定是满足条件的。
另外当顶点高度全部相同时,不可能连接第三条边。只能两两相连,故边数为顶点数的一半。
void solve()
{		
	int n;
	cin >> n;
	for (int i = 1; i <= n; i ++) cin >> a[i];
	sort(a + 1, a + 1 + n);
	if (a[1] == a[n]) {
		cout << n / 2 << endl;
		return;
	}
	LL ans = 0;
	for (int i = 1; i <= n; i ++){
		int j = i;
		while (j + 1 <= n && a[j + 1] == a[i]) j ++;
		ans = max(ans, (LL)j * (n - j));
		i = j;
	}
	
	cout << ans << endl;
}
D - Doremy's Pegging Game
题意:

思路:
只有当在(n + 1) / 2范围内,有若干点和与其中心对称的地方有一个点的情况下,去掉任意一个点,会产生答案。
故而枚举范围和在范围内选取的点数,还有与其中心对称的点的个数再乘上其他点的全排列
将答案整合加起来即为一个点的所有可能答案。再乘以n即为所有点的可能的答案。
若n为偶数,则存在只有两个点产生答案的可能。故而当n为偶数的时候加上n-2的全排列
思路原作者
typedef long long LL;
const int M = 5010;
int fact[M], infact[M];
int n, p;
 
LL qmi(LL a, LL b, int p) {
	LL res = 1;
	while (b) {
		if (b & 1) res = res * a % p;
		b >>= 1;
		a = a * a % p;
	}
 
	return res;
}
 
void Init() {
	fact[0] = infact[0] = 1;
	for (int i = 1; i <= M; i ++) {
		fact[i] = (LL)fact[i - 1] * i % p;
		infact[i] = (LL)infact[i - 1] * qmi(i, p - 2, p) % p;
	}
}
 
LL C(int n, int m) {
	if (n < m || m < 0) return 0;
	return (LL)fact[n] * infact[m] % p * infact[n - m] % p;
}
 
LL P(int n, int m) {
	if (n < m || m < 0) return 0;
	return (LL)fact[n] * infact[m] % p;
}
 
//注意观察N的大小
void solve() {
	cin >> n >> p;
	Init();
	LL ans = 0;
	if (n % 2 == 0) ans = (ans + fact[n - 2]) % p;
	for (int i = 2; i <= (n + 1) / 2; i ++){
		for (int j = 2; j <= i; j ++){
			LL x = C(i - 2, j - 2);
			LL y = i - n % 2;
			ans = (ans + x * y % p * fact[n - j - 1] % p) % p;
		}
	}
	
	ans = ans * n % p;
	cout << ans << endl;
}
 
总结:三四题都是补的,思路过于狭隘。放不开。对于稍微复杂一点的题就完全没有思路

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号