cf1615C 贪心/数学/1600
C - Menorah
两个01串s1和s2。求最少的操作数把s1变为s2,不能则为-1
操作:固定一个1,其余位全部取反
我们的目标是让所有的位置变得相同。
考虑两个字符串相同的0**(00)和1(11)的数量,以及不同的0(01)和1(10)**的数量。
一个位置点两次是没有意义的,而连续点两个位置相当于交换了两个位置。(1和0)
所以对于当前不同的,即01,10:我们有两种策略:
- 点不同的位置。如果不同的位置的1和0数量相等,即可全部交换。因为点了偶数次所以对初始相等的不造成影响
- 点相同的位置。相同的位置点奇数次,即可让不同的位置变成相同,那么问题转换成了如何点奇数次使得相同的位置不变。
- 我们只需要让1的数量比0的数量多1,即可在偶数次交换01后使有一个11,而其他的全部不同。
#include <bits/stdc++.h>
using namespace std;
inline void read(int &a) {a=0;int c=getchar(),b=1; while(c>'9'||c<'0') {if(c=='-')b=-1;c=getchar();} while(c>='0'&&c<='9') a=(a<<3)+(a<<1)+c-48,c=getchar();a*=b; }
/**/
const int N = 1e5 + 5;
int t, n, sc1, sc0, dc1, dc0;
char s1[N], s2[N];
/**/
int main()
{
read(t);
while(t--)
{
read(n);
scanf("%s%s", s1 + 1, s2 + 1);
sc1 = sc0 = dc1 = dc0 = 0;
for(int i = 1; i <= n; i++)
{
if(s1[i] == s2[i])
{
if(s1[i] == '1') sc1++;
else sc0++;
}
else
{
if(s1[i] == '1') dc1++;
else dc0++;
}
}
int ans = 0x3f3f3f3f;
if(dc0 == dc1) ans = min(ans, dc0 + dc1);
if(sc1 == sc0 + 1) ans = min(ans, sc1 + sc0);
if(ans == 0x3f3f3f3f) cout << -1 << '\n';
else cout << ans << '\n';
}
return 0;
}