Codeforces Round 1014 (Div. 2)


A. Kamilka and the Sheep

题意:给你\(n\)个数,给每个数加上一个非负整数后,选出两个数使得它们的\(gcd\)最大。

因为\(gcd(x, y) = gcd(x, y - x)\)。然后我猜是\(max-min\)

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::ranges::sort(a);
    std::cout << a.back() - a[0] << "\n";
}

B. Lady Bug

题意:给你两个01串,每次可以交换\(a_i, b_{i-1}\)或者\(a_i, b_{i+1}\)。求能不能使得第一个串全是0。

第一个串的奇数位置和第二个串的偶数位置是联通的,偶数位置和第二个串的奇数位置是联通的。这两个联通块里1的数量不能超过其一半。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::string s, t;
    std::cin >> s >> t;
    int cnt1 = 0, cnt2 = 0;
    for (int i = 0; i < n; ++ i) {
    	if (i & 1) {
    		cnt2 += s[i] == '1';
    		cnt1 += t[i] == '1';
    	} else {
    		cnt1 += s[i] == '1';
    		cnt2 += t[i] == '1';
    	}
    }
    //1010
    //0001

    if (cnt1 > n / 2 || cnt2 > (n + 1) / 2) {
    	std::cout << "NO\n";
    } else {
    	std::cout << "YES\n";
    }
}

C. Asuna and the Mosquitoes

题意:给你一个数组,每次选一个奇数和一个偶数,然后使得其中一个加一,另一个减一,求可以得到的最大值。

一个奇数和偶数一直操作可以得到它们的和,也是一个奇数。那么只要有奇数就可以拿到所有偶数。同时我们可以让每个偶数和一个奇数操作使得奇数变成1,偶数变成它们的和减一。那么我们可以到达总和减奇数个数减一的值。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a, b;
    for (int i = 0; i < n; ++ i) {
    	int x;
    	std::cin >> x;
    	if (x & 1) {
    		a.push_back(x);
    	} else {
    		b.push_back(x);
    	}
    }

    std::ranges::sort(a, std::greater<>());
    std::ranges::sort(b, std::greater<>());

    if (a.empty()) {
    	std::cout << b[0] << "\n";
    	return;
    } else if (b.empty()) {
    	std::cout << a[0] << "\n";
    	return;
    }

    i64 ans = std::accumulate(b.begin(), b.D. Mishkin Energizerend(), 0ll) + a[0];
    for (int i = 1; i < a.size(); ++ i) {
    	ans += a[i] - 1;
    }

    std::cout << ans << "\n";
}

D. Mishkin Energizer

模拟题,但一直wa3。
赛后检查发现,在第一步的时候我们想到出现次数第二第三多的元素可能都没有相邻。太痛了。

题意:给你一个只包含'\(L\)', '\(I\)', '\(T\)'字符串,你要使得它们出现的次数相等,每次可以选两个相邻的不一样的元素,把第三个元素插在中间。

其实思路很简单,\(n\)很小,直接模拟就行。我们只需要把出现次数最少的操作到和次数第二小的元素一样,然后把这两个元素变到和最大的一样就行。
如何模拟?我们用0,1,2表示三个元素,那么我们想插1,2这两个元素,可以在\(12\)中间插,\(12 -> 102 -> 1202 -> 10202..\),插入的位置一直一样,或者是\(21\)中间插,\(21 -> 201 -> 2021 -> 20201...\),插入位置每次加一。
代码很丑,因为赛时调了很久。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::string s;
    std::cin >> s;
    std::vector<int> a(n);
    std::vector<std::pair<int, int>> cnt{{0, 0}, {0, 1}, {0, 2}};
    for (int i = 0; i < n; ++ i) {
    	if (s[i] == 'L') {
    		a[i] = 0;
    		cnt[0].first += 1;
    	} else if (s[i] == 'I') {
    		a[i] = 1;
    		cnt[1].first += 1;
    	} else {
    		a[i] = 2;
    		cnt[2].first += 1;
    	}
    }

    std::vector<int> ans;
    auto work1 = [&](std::vector<int> & a) -> bool {
    	for (int i = 0; i + 1 < a.size(); ++ i) {
    		//120202
    		if (a[i] == cnt[1].second && a[i + 1] == cnt[2].second) {
    			while (cnt[0].first < cnt[1].first) {
    				ans.push_back(i);
    				if (ans.size() > 2 * n) {
    					return false;
    				}
    				a.insert(a.begin() + i + 1, cnt[0].second);
    				++ cnt[0].first;
    				if (cnt[0].first != cnt[1].first) {
    					ans.push_back(i);
	    				if (ans.size() > 2 * n) {
		    				return false;
		    			}
	    				a.insert(a.begin() + i + 1, cnt[2].second);
	    				++ cnt[2].first;
    				}
    			}
    			return true;
    		}

    		//2021
    		if (a[i] == cnt[2].second && a[i + 1] == cnt[1].second) {
    			while (cnt[0].first < cnt[1].first) {
    				ans.push_back(i);
    				if (ans.size() > 2 * n) {
    					return false;
    				}
    				a.insert(a.begin() + i + 1, cnt[0].second);
    				++ i;
    				++ cnt[0].first;
    				if (cnt[0].first != cnt[1].first) {
    					ans.push_back(i);
	    				if (ans.size() > 2 * n) {
		    				return false;
		    			}
	    				a.insert(a.begin() + i + 1, cnt[2].second);
	    				++ cnt[2].first;
	    				++ i;
    				}
    			}
    			return true;
    		}
    	}

    	for (int i = 0; i + 1 < a.size(); ++ i) {
    		if (a[i] == cnt[0].second && a[i + 1] == cnt[2].second) {
    			ans.push_back(i);
				if (ans.size() > 2 * n) {
					return false;
				}
				a.insert(a.begin() + i + 1, cnt[1].second);
				++ cnt[1].first;
				return true;
    		}

    		if (a[i] == cnt[2].second && a[i + 1] == cnt[0].second) {
    			ans.push_back(i);
				if (ans.size() > 2 * n) {
					return false;
				}
				a.insert(a.begin() + i + 1, cnt[1].second);
				++ cnt[1].first;
				return true;
    		}

    		if (a[i] == cnt[0].second && a[i + 1] == cnt[1].second) {
    			ans.push_back(i);
				if (ans.size() > 2 * n) {
					return false;
				}
				a.insert(a.begin() + i + 1, cnt[2].second);
				++ cnt[2].first;
				return true;
    		}

    		if (a[i] == cnt[2].second && a[i + 1] == cnt[1].second) {
    			ans.push_back(i);
				if (ans.size() > 2 * n) {
					return false;
				}
				a.insert(a.begin() + i + 1, cnt[2].second);
				++ cnt[2].first;
				return true;
    		}
    	}

    	return true;
    };

    auto work2 = [&](std::vector<int> & a) -> bool {
    	for (int i = 0; i + 1 < a.size(); ++ i) {
    		//201010
    		if (a[i] == cnt[2].second && a[i + 1] == cnt[0].second) {
    			while (cnt[0].first < cnt[2].first) {
    				ans.push_back(i);
    				if (ans.size() > 2 * n) {
	    				return false;
	    			}
    				a.insert(a.begin() + i + 1, cnt[1].second);
    				++ cnt[1].first;
					ans.push_back(i);
    				if (ans.size() > 2 * n) {
	    				return false;
	    			}
    				a.insert(a.begin() + i + 1, cnt[0].second);
    				++ cnt[0].first;
    			}
    			return true;
    		}

    		if (a[i] == cnt[2].second && a[i + 1] == cnt[1].second) {
    			while (cnt[1].first < cnt[2].first) {
    				ans.push_back(i);
    				if (ans.size() > 2 * n) {
	    				return false;
	    			}
    				a.insert(a.begin() + i + 1, cnt[0].second);
    				++ cnt[0].first;
					ans.push_back(i);
    				if (ans.size() > 2 * n) {
	    				return false;
	    			}
    				a.insert(a.begin() + i + 1, cnt[1].second);
    				++ cnt[1].first;
    			}

    			return true;
    		}

    		if (a[i] == cnt[0].second && a[i + 1] == cnt[2].second) {
    			while (cnt[0].first < cnt[2].first) {
    				ans.push_back(i);
    				if (ans.size() > 2 * n) {
    					return false;
    				}
    				a.insert(a.begin() + i + 1, cnt[1].second);
    				++ i;
    				++ cnt[1].first;
					ans.push_back(i);
    				if (ans.size() > 2 * n) {
	    				return false;
	    			}
    				a.insert(a.begin() + i + 1, cnt[0].second);
    				++ cnt[0].first;
    				++ i;
    			}
    			return true;
    		}

    		if (a[i] == cnt[1].second && a[i + 1] == cnt[2].second) {
    			while (cnt[1].first < cnt[2].first) {
    				ans.push_back(i);
    				if (ans.size() > 2 * n) {
    					return false;
    				}
    				a.insert(a.begin() + i + 1, cnt[0].second);
    				++ i;
    				++ cnt[0].first;
					ans.push_back(i);
    				if (ans.size() > 2 * n) {
	    				return false;
	    			}
    				a.insert(a.begin() + i + 1, cnt[1].second);
    				++ cnt[1].first;
    				++ i;
    			}
    			return true;
    		}
    	}

    	return false;
    };

    std::ranges::sort(cnt);
    if (cnt[0].first == cnt[2].first) {
    	std::cout << 0 << "\n";
    } else {
		while (cnt[0].first != cnt[1].first) {
			if (!work1(a)) {
	    		std::cout << -1 << "\n";
	    		return;
	    	}
		}

    	std::ranges::sort(cnt);
		if (cnt[0].first != cnt[2].first) {
			if (!work2(a)) {
	    		std::cout << -1 << "\n";
	    		return;
	    	}
	    }
    	std::cout << ans.size() << "\n";
    	for (auto & x : ans) {
    		std::cout << x + 1 << "\n";
    	}

    	// for (auto & x : a) {
    	// 	std::cout << x;
    	// }
    	// std::cout << "\n";
    	// int x = std::ranges::count(a, 0);
    	// int y = std::ranges::count(a, 1);
    	// int z = std::ranges::count(a, 2);
    	// if (x != y || x != z || y != z) {
    	// 	std::cout << "!!!!" << "\n";
    	// 	return;
    	// }
    }
}

E. She knows...

题意:一个\(n\times m\)\(01\)矩阵,有\(k\)个位置填好了,其它格子等你去填,求使得格子上一边是黑色一边是白色的边的数量是偶数的方案数是多少。

如果把黑色格子的联通块拿出来,发现除了有和边界(除四个角外)相连的,其它的边界周长都是偶数。
那么实际是要求边上为1的格子是偶数个。
那么记录在边上的格子,如果已经都填好了,判断是不是偶数个1,不是答案为0,否则为\(2^{n\times m - k}\)。如果有没填好的,留一个格子不填,其它随便填,然后这个格子随机应变。答案为\(2^{n\times m - k - 1}\)。虽说很简单,但看不出来之和边界有关的话,似乎无法做。
代码省略取模类。

点击查看代码
void solve() {
    i64 n, m, k;
    std::cin >> n >> m >> k;
    i64 tot = 2LL * (n + m) - 8;
    int s = 0;
    for (int i = 0; i < k; ++ i) {
    	int x, y, z;
    	std::cin >> x >> y >> z;
    	if ((x == 1) ^ (x == n) ^ (y == 1) ^ (y == m)) {
    		s ^= z;
    		tot -= 1;
    	}
    }

    if (tot == 0) {
    	if (s) {
    		std::cout << 0 << "\n";
    	} else {
    		std::cout << power<Z>(2, n * m - k) << "\n";
    	}
    } else {
    	std::cout << power<Z>(2, n * m - k - 1) << "\n";
    }
}	
posted @ 2025-03-30 01:55  maburb  阅读(591)  评论(0)    收藏  举报