翻译:
马克刚买了一架𝑛灯泡。灯泡的状态可以用二进制字符串𝑠=𝑠1𝑠2…𝑠𝑛来描述,其中𝑠𝑖=𝟷表示𝑖-th灯泡是打开的,而𝑠𝑖=𝟶表示𝑖-th灯泡是关闭的。
不幸的是,灯泡坏了,他唯一能做的改变灯泡状态的操作是:
选择一个指数𝑖从2、3、…,𝑛−1这样𝑠𝑖−1≠𝑠𝑖+ 1。
切换𝑠𝑖。即,如果𝑠𝑖为𝟶,则将𝑠𝑖设置为𝟷,反之亦然。
Mark希望灯泡的状态是另一个二进制字符串𝑡。帮助Mark确定这样做的最小操作数。
输入
输入的第一行包含单个整数𝑞(1≤𝑞≤104)—测试用例的数量。
每个测试用例的第一行包含单个整数𝑛(3≤𝑛≤2⋅105)——灯泡的数量。
每个测试用例的第二行包含一个长度为𝑛的二进制字符串𝑠——灯泡的初始状态。
每个测试用例的第三行包含一个长度为𝑛的二进制字符串𝑡——灯泡的最终状态。
保证所有测试用例𝑛的总和不超过2⋅105。
输出
对于每个测试用例,打印一行,其中包含Mark将𝑠转换为𝑡所需执行的最小操作数。如果没有这样的操作顺序,则打印−1。
例子
inputCopy
4
4
0100
0010
4
1010
0100
5
01001
00011
6
000101
010011
outputCopy
2
-1
-1
5
请注意
在第一个测试用例中,实现最小操作数量的操作序列如下所示。
选择𝑖=3,将𝟶𝟷𝟶𝟶更改为𝟶𝟷𝟷𝟶。
选择𝑖=2,将𝟶𝟷𝟷𝟶更改为𝟶𝟶𝟷𝟶。
在第二个测试用例中,没有操作序列,因为不能更改𝑠的第一个数字或最后一个数字。
在第三个测试用例中,即使𝑠和𝑡的第一个数字是相同的,𝑠和𝑡的最后一个数字是相同的,但可以表明不存在满足条件的操作序列。
在第四个测试用例中,实现最小操作次数的一个序列如下:
选择𝑖= 3,改变𝟶𝟶𝟶𝟷𝟶𝟷,𝟶𝟶𝟷𝟷𝟶𝟷。
选择𝑖= 2,改变𝟶𝟶𝟷𝟷𝟶𝟷,𝟶𝟷𝟷𝟷𝟶𝟷。
选择𝑖= 4,改变𝟶𝟷𝟷𝟷𝟶𝟷,𝟶𝟷𝟷𝟶𝟶𝟷。
选择𝑖= 5,改变𝟶𝟷𝟷𝟶𝟶𝟷,𝟶𝟷𝟷𝟶𝟷𝟷。
选择𝑖= 3,改变𝟶𝟷𝟷𝟶𝟷𝟷,𝟶𝟷𝟶𝟶𝟷𝟷。
思路:
这道题利用其性质来写 0 1 1 1 0 0
如果要变成 0 0 0 1 1 0
则需要移动 0 1 2 2 3 ,一共3步
相对应的,就可以变成 0 1 0 0 1 0
0 0 0 1 0 1
就是其对应的1的位置相减,1的块数还要相等,所以判断块数来决定是否是-1,然后总花费就是abs(i-j)
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long ll;
int n,t;
inline __int128 read(){
__int128 x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
//这道题利用其性质来写 0 1 1 1 0 0
//如果要变成 0 0 0 1 1 0
//则需要移动 0 1 2 2 3 ,一共3步
//相对应的,就可以变成 0 1 0 0 1 0
// 0 0 0 1 0 1
//就是其对应的1的位置相减,1的块数还要相等,所以判断块数来决定是否是-1,然后总花费就是abs(i-j)
string a,b;
int a1[200005],b1[200005];
void solv(){
cin>>n>>a>>b;
for (int i =n-1; i>=0; i--) {
a1[i]=a[i]-'0';
}
for (int i =n-1; i>=0; i--) {
b1[i]=b[i]-'0';
}
if (a[0]!=b[0]||a[n-1]!=b[n-1]) {
printf("-1\n");return;
}
int kkl=0;
for (int i=n-1; i>0; i--) {
a1[i]=a1[i]^a1[i-1];
if (a1[i]==1) {
kkl++;
}
}
for (int i=n-1; i>0; i--) {
b1[i]=b1[i]^b1[i-1];
if (b1[i]==1) {
kkl--;
}
}
if (kkl!=0) {
printf("-1\n");return;
}
// for (int i = 0; i<n; i++) {
// printf("%d ",a1[i]);
// }printf("\n");
// for (int i = 0; i<n; i++) {
// printf("%d ",b1[i]);
// }printf("\n");
ll ans=0;
for (int i =n-1,j=n-1; i&&j;) {
// printf("%d %d\n",i,j);
if (a1[i]&&b1[j]) {
ans+=abs(i-j);
i--;
j--;
continue;
}
if (a1[i]) {
j--;
}
else{
i--;
}
}
printf("%lld\n",ans);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
cin>>t;
while (t--) {
solv();
}
return 0;
}