+1会把前面所有1变成0,第一个0变成1,也就是批量消除前缀1,显然他只会用一次,
枚举时机就好了
如果a[i]是0,次数为a[0 ~ i-1]中0的个数+b[0 ~ i-1]中1的个数+1(+1次数)+后面常规替换次数,如果b[i]=0还要把a[i]变一次
如果a[i]是1 花一次机会把a[i]变成0 同上.
#include
#include
#include
using namespace std;
int a[100010],b[100010];
int d[100010];
int n;
int main()
{
int T;
scanf("%d",&T);
for (int tp = 1; tp <= T; tp++) {
scanf("%d",&n);
//a->b
for (int i = 0; i <= n+10; i++) {
d[i] = 0;
a[i] = b[i] = 0;
}
for (int i = 1; i <= n; i++) {
char c = getchar();
while (c!='0' && c!='1') {
c = getchar();
}
if(c=='0') a[i] = 0;
else a[i] = 1;
}
for (int i = 1; i <= n; i++) {
char c = getchar();
while (c!='0' && c!='1') {
c = getchar();
}
if(c=='0') b[i] = 0;
else b[i] = 1;
}
int a0 = 0,b1 = 0;
a[n+1] = 0;
b[n+1] = 0;
d[n+1] = d[n+2] = 0;
//cout<<(a+1);
for (int i = n; i >= 1; i--)
if (a[i] == b[i])
d[i] = d[i+1];
else
d[i] = d[i+1]+1;
int ans = d[1];
for (int i = 1; i <= n+1; i++) {
if (a[i] == 0) {
int tmp = a0+b1+1+d[i+1];
if (b[i] == 0) tmp++;
ans = min(ans, tmp);
} else {
int tmp = a0+b1+1+1+d[i+1];
if (b[i] == 0) tmp++;
ans = min(ans, tmp);
}
if (a[i] == 0) a0++;
if (b[i] == 1) b1++;
}
cout<<ans<<endl;
}
return 0;
}
你有两个无限长01串S,T,分别记作S0S1…和T0T1…。其中S和T从n位之后都是0,也就是当i≥n,有Si=Ti=0。
你可以对S串进行操作:
问最少的步数将S变成T。
Input
第一行一个正整数T(1≤T≤104)表示数据组数。
对于每组数据,第一行一个整数n,接下来两行长度为n(1≤n≤105)的01串S和T,表示S和T的前n位。
保证∑n≤106。
Output
对于每组数据,输出一个整数,表示步数。
Sample Input
3
5
11111
00000
5
10100
01010
5
00000
00001
Sample Output
2
3
1
Hint
第一组数据中,可以选择先加一变成 “000001”,然后将S5变成 ‘0’。
第二组数据中,先加一变为 “01100”,然后直接修改。
第三组数据中,直接修改。