CF1057 BCD - 教程
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的最小操作次数,容易得到转移方程:
d p [ i ] = m i n ( d p [ i − 2 ] + c o s t 1 , d p [ i − 3 ] + c o s t 2 ) 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;
}

浙公网安备 33010602011771号