#879 div2
A:
题目:
现在存在一个只由 - 1, 1 构成的数组,如果说一个数组是好数组,数组所有数的乘积是 1,数组所有数的和是>=0.
思路:
首先如果保证数组和>=1, 那么正数的个数>=负数的个数,乘积为1表示,负数的个数是偶数。
这两个条件前者优先级大于后者,如果说正数>=负数,那么不用考虑这个条件,观察条件2是否满足,不满足则多加一个正数,否则减少负数增加正数,直到符合条件,这时
再看第二条件是否成立,否则就多减少一个负数来保证。
代码
void solved()
{
cin >> n;
int cnt1 = 0, cntf1 = 0;
for(int i = 0; i < n; i++)
{
int x; cin >> x;
if(x == 1) cnt1++;
else cntf1++;
}
if(cnt1 >= cntf1 && cntf1 % 2 == 0)
{
cout << 0 << endl;
return;
}
int ans = 0;
if(cnt1 < cntf1)
{
while(cnt1 < cntf1) cnt1++, cntf1--, ans++;
if(cntf1 % 2 != 0) ans++;
}else if(cnt1 > cntf1)
{
ans = 1;
}else
{
ans = 1;
}
cout << ans << endl;
}
B:
题目:
现在存在一个一个范围 L - R, 找到这个范围内两个数字的对应位置上数字绝对值差和的最大值。
思路:
观察样例发现构造 0 - 9, 9 - 0, 是理想优情况。
观察样例 L 和 R,如果说从前往后的位数是相同的,那么肯定不用考虑这几位数。 从变化的一位开始看起。
变化这位后面的位数,可以满足下届的情况下任取,所以我们可以让 L 后面的位数去构造 .... 9 0 9 0,让R后面的数去构造
0 9 0 9, 因为 L是范围内最小的数字,后面位数任取,所以去构造 9开头的9 0 9 0,R是范围内最大的数字,后面任取 0 9 09
代码:
void solved()
{
string a, b; cin >> a >> b;
if(b.size() > a.size()) swap(a, b);
int nb = b.size();
for(int i = 0; i < a.size() - nb; i++) b = "0" + b;
int ans = 0;
int pos = a.size();
for(int i = 0; i < a.size(); i++)
{
if(a[i] != b[i])
{
ans += abs(a[i] - b[i]), pos = i + 1;
break;
}
}
ans += (a.size() - 1 - pos + 1) * 9;
cout << ans << endl;
}
C:
题目:
先存在一个游戏,游戏存在两个字符串 S 和 T , A先手可以改变一个字符,B后手可以任意选择一个字符串完全反转。
当两个字符串完全相同游戏结束,A尽可能结束游戏,B尽可能拖延游戏,两者采取最优,几次操作后结束游戏。
思路:
考虑 B 操作,B操作偶数次,相当于没有反转,无论是两次都反转同一,或者各自反转,最终都是同一情况。
首先A 有两种结束游戏方式:一种按照开局直接按照当前顺序改变 A - B,或者把 A 变成,反转 B。
操作A 和操作B,都是等价的。
如果按照当前顺序改变A-B,那么要保证,B操作次数是偶数,否则需要再翻转一次。
如果A改变反B,那么 B要奇数次,因为必须要翻转一次。
做法:
统计两种方式操作次数,判断奇偶情况,对于第二种来说,即使A和B反转完全相同,但是仍然需要两次操作,因为
必须翻转一次,所以和2取ax
代码
void solved()
{
cin >> n;
string a, b; cin >> a >> b;
int ans1, ans2;
int cnt1 = 0;
int cnt2 = 0;
for(int i = 0; i < n; i++)
{
if(a[i] != b[i]) cnt1++;
if(a[i] != b[n - i - 1]) cnt2++;
}
if(cnt1 % 2 == 0) ans1 = cnt1 + cnt1;
else ans1 = cnt1 + cnt1 - 1;
if(cnt2 % 2 == 0) ans2 = max((LL)2, cnt2 + cnt2 - 1);
else ans2 = cnt2 + cnt2;
cout << min(ans1, ans2) << endl;
}