CF1057 BCD
仪表板 - Codeforces 第 1057 轮(第 2 组) - Codeforces — Dashboard - Codeforces Round 1057 (Div. 2) - Codeforces
B. Bitwise Reversion
题意:给定x,y,z;考虑是否存在a&b=x,b&c=y,a&c=z。
思路:按位分类讨论,发现如果有且仅有两个数同一位为1,比如x y最高位为1,那么a b c最高位都要为1,但是那样又不能满足a&c在这一位为0了。故无解。
void solve()
{cin >> x >> y >> z;rep(0, i, 32){num = 0;if ((x >> i & 1) + (y >> i & 1) + (z >> i & 1) == 2){no;re;}}yes;
}
C. Symmetrical Polygons
题意:给一些边,保证组成的图像具有对称性和可连接性。求最大周长。
思路:
先考虑对称性:出现的偶数次可以放在两边;奇数次算剩下多余的一个,最多可以上下放一个,类比等腰梯形。
再考虑可连接性,类比三角形两边之和大于第三边,我们分别考虑选一条奇数边和两条奇数边,都要保证最长的那条奇数边<其余之和。
void solve()
{cin >> n;vector<int> c(n + 1);rep(1, i, n){cin >> c[i];}map<int, int> pre;rep(1, i, n){pre[c[i]]++;}vector<int> vec;sum = 0;for (auto &[val, cnt] : pre){if (cnt % 2 == 0){sum += val * cnt;}else{sum += val * ((cnt)-1);vec.emplace_back(val);}}if (sum == 0){cout << 0;re;}sort(all(vec));if ((int)vec.size() <= n - 4) //前面sum加的都是偶数,所以此时至少要有四条边才有赋值{ans = sum;}else{ans = 0;}for (auto i : vec) //考虑选一条奇数边{if (sum > i)ans = max(ans, sum + i);}if(vec.size()>=2) //考虑选两条奇数边for (int i = 0; i < vec.size() - 1; i++){if (sum + vec[i] > vec[i + 1]){ans = max(ans, sum + vec[i] + vec[i + 1]);}}cout << ans;
}
D. Not Alone
题意:给一个数组,每次可以对任意一个数±1\pm1±1,问保证每个数都存在相邻位置和它一样的数(环形),最少操作次数是多少?
思路:先不考虑环形,考虑简单的链状,任意n可以拆成2x+3y,所以我们可以把数组拆成2、3的块相连。
我们令dp[i]为从1到i的最小操作次数,容易得到转移方程:
dp[i]=min(dp[i−2]+cost1,dp[i−3]+cost2)dp[i]=min(dp[i-2]+cost1,dp[i-3]+cost2)dp[i]=min(dp[i−2]+cost1,dp[i−3]+cost2) ,cost1表示i-1操作到i的次数,cost2表示操作i-2、i-1、i相等的最少次数。
现在考虑环形的限制,环形无非就是首尾一部分可以相连,显然对答案有影响的只有后三位,所以我们将所有数循环左移三次。
void solve()
{cin >> n;rep(1, i, n){cin >> a[i];}ans = 1e18;auto w = [&](int x, int y, int z) //cost2{auto mx = max({x, y, z});auto mi = min({x, y, z});return mx - mi;};rep(0, i, 3){dp[0] = 0;dp[1] = inf;rep(2, j, n){dp[j] = dp[j - 2] + abs(a[j - 1] - a[j]);if (j >= 3){dp[j] = min(dp[j], dp[j - 3] + w(a[j - 2], a[j - 1], a[j]));}}ans = min(ans, dp[n]);rotate(a + 1, a + 2, a + n + 1); //循环左移}cout << ans;
}