一种操作,可以选择前缀长度为k,翻转前k的01值然后顺序再倒一下。
要求在2n步内把给定a串变成b串
做法:
a:01101 01001
b:10000 10001
以这个为例,因为要求是2n步内,很容易就想到每个点搞最多两次搞出来,于是就可以2步之内缩小一次问题规模,从n一直缩小到0;
a[1]和b[n]要对上,直接前k翻转.
现在变成谁和谁对上?b[n]和a[n]现在都可以不用管了,于是来到了b[n-1],那b[n-1]和谁对上了,当然还是a[1],a[1]可不就是上一个a[n]吗?可是我们还要用一个值记录全体翻转了几次,(a[1]+i)%2才是真正的值。然后我们发现这个a[1]在原序列中跳跃是这样的
pos=: 1 n 2 n-1 3 …一直到n/2;
于是代码就出来了:
code
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <iomanip>
//
using namespace std;
const int INF = 0x3f3f3f3f;//1.06e9大小
const int mod = 1e9 + 9;
const int mod2 = 998244353;
const int mod3 = 1e9;
const double PI = 3.14159265;
const double eps =1e-8;
typedef unsigned long long ULL;
typedef long long LL;
const int sq5=616991993;
#define ms(x, n) memset(x,n,sizeof(x))
#define debug printf("***debug***\n")
#define pii pair<int ,int>
#define X first
#define Y second
#define pb push_back
//以下define不能在团队赛中使用
#define rep(i,from,to) for(int i=from;i<=to;++i)
#define per(i,from,to) for(int i=from:i>=to;--i)
/*
*/
const int MAXN = 1e5+10;
int a[MAXN];
int b[MAXN];
int ans[2*MAXN];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i){scanf(" %c",&a[i]);a[i]-='0';}
for(int i=1;i<=n;++i){scanf(" %c",&b[i]);b[i]-='0';}
int cnt=0;//0表示相向匹配,1为同比较
int pos=1;
for(int i=1;i<=n;++i)
{//a的pos和b的n-i+1位
if(b[n-i+1]==(a[pos]+i-1)%2)ans[cnt++]=1;
ans[cnt++]=n-i+1;
if(pos<=n/2)pos=n-pos+1;
else pos=n-pos+2;
}
printf("%d ",cnt);
for(int i=0;i<cnt;++i)printf("%d ",ans[i]);
printf("\n");
}
return 0;
}