D. Serval and Shift-Shift-Shift

D. Serval and Shift-Shift-Shift

Serval has two n-bit binary integer numbers a and b. He wants to share those numbers with Toxel.

Since Toxel likes the number b more, Serval decides to change a into b by some (possibly zero) operations. In an operation, Serval can choose any positive integer k between 1 and n, and change a into one of the following number:

  • a(ak)
  • a(ak)

In other words, the operation moves every bit of a left or right by k positions, where the overflowed bits are removed, and the missing bits are padded with 0. The bitwise XOR of the shift result and the original a is assigned back to a.

Serval does not have much time. He wants to perform no more than n operations to change a into b. Please help him to find out an operation sequence, or determine that it is impossible to change a into b in at most n operations. You do not need to minimize the number of operations.

In this problem, xy denotes the bitwise XOR operation of x and y. ak and ak denote the logical left shift and logical right shift.

Input

Each test contains multiple test cases. The first line contains the number of test cases t (1t2103). The description of the test cases follows.

The first line of each test case contains a single integer n (1n2103) — the number of bits in numbers a and b.

The second and the third line of each test case contain a binary string of length n, representing a and b, respectively. The strings contain only characters 0 and 1.

It is guaranteed that the sum of n over all test cases does not exceed 2103.

Output

For each test case, if it is impossible to change a into b in at most n operations, print a single integer 1.

Otherwise, in the first line, print the number of operations m (0mn).

If m>0, in the second line, print m integers k1,k2,,km representing the operations. If 1kin, it means logical left shift a by ki positions. If nki1, it means logical right shift a by ki positions.

If there are multiple solutions, print any of them.

Example

input

复制代码
3
5
00111
11000
1
1
1
3
001
000
复制代码

output

2
3 -2
0
-1

Note

In the first test case:

The first operation changes a into 0011100111000_=11111.

The second operation changes a into 1111100_11111=11000.

The bits with strikethroughs are overflowed bits that are removed. The bits with underline are padded bits.

In the second test case, a is already equal to b, so no operations are needed.

In the third test case, it can be shown that a cannot be changed into b.

 

解题思路

  官方给出的题解写得很好,我就按照其思路来写了。

  首先当且仅当ab均为全0ab均不全为0才有解。

  如果a为全0,那么很明显不管如何操作a始终均为全0,因此如果b不全为0那么无解。

  如果a不全为0,由于每次操作至少左移或者右移一位,因此位移后的结果一定与原串不同,因此异或后的结果一定不为0。所以如果b为全0那么无解。

  然后就是ab均不全为0的情况了,可以证明一定存在一种方案使得在不超过n次的操作下让a变成b。定义lb(a)a的最低位的1的位,hb(a)a的最高位的1的位。这里的高低位与二进制的规则相同,即最左边为最高位,最右边为最低位。然后按照下面的4个步骤来进行构造:

  1. 如果hb(a)<lb(b),那么将a左移lb(b)hb(a)位,然后异或。经过这步操作后(可能没有)一定有hb(a)lb(b)
  2. 考虑lb(b)1,lb(b)2,,1的每一位i(注意到此时bi均为0),如果ai=1,那么我们将a右移hb(a)i位然后异或,那么就能将ai置成0。完成后就会有lb(a)lb(b)
  3. 如果是lb(a)>lb(b)的情况,我们将a右移lb(a)lb(b)位然后异或,使得lb(a)=lb(b)
  4. 考虑lb(b)+1,lb(b)+2,,n的每一位i,如果aibi,那么将a左移ilb(a)位然后异或,那么就能将ai置成bi。完成后就一定会有a=b

  可以发现第2步与第4步一共最多需要n1次操作。而第1步与第3步一定不会同时出现,这是因为如果执行了第1步那么一定会有lb(a)=lb(b)而不用执行第3步。因此我们最多使用n次操作就可以把a变成b

  AC代码如下,时间复杂度为O(n2)

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 2e3 + 10;
 5 
 6 char sa[N], sb[N];
 7 int a[N], b[N];
 8 
 9 void solve() {
10     int n;
11     scanf("%d %s %s", &n, sa, sb);
12     if (!strcmp(sa, sb)) {    // a和b相等
13         printf("0\n");
14         return;
15     }
16     int ha = n, lb = -1;
17     for (int i = 0; i < n; i++) {
18         a[i] = sa[i] - '0';
19         if (a[i] && ha == n) ha = i;
20     }
21     for (int i = 0; i < n; i++) {
22         b[i] = sb[i] - '0';
23         if (b[i]) lb = i;
24     }
25     if (ha == n || lb == -1) {    // a或b有一个全为0,无解
26         printf("-1\n");
27         return;
28     }
29     vector<int> ans;
30     if (ha > lb) {
31         int d = ha - lb;    // 将a左移ha-lb位
32         for (int i = lb; i + d < n; i++) {
33             a[i] ^= a[i + d];
34         }
35         ha = lb;    // a的最高位变成了lb
36         ans.push_back(d);
37     }
38     for (int i = lb + 1; i < n; i++) {    // 在lb+1...n-1位中把a[i]为1的位变成0
39         if (a[i]) {
40             int d = i - ha;    // 右移i-ha位
41             for (int j = n - 1; j >= i; j--) {
42                 a[j] ^= a[j - d];
43             }
44             ans.push_back(-d);
45         }
46     }
47     int la;    // 求a的最低位的1
48     for (int i = lb; i >= 0; i--) {
49         if (a[i]) {
50             la = i;
51             break;
52         }
53     }
54     if (la < lb) {
55         int d = lb - la;    // 通过把a右移lb-la位使得la=lb
56         for (int i = lb; i - d >= 0; i--) {
57             a[i] ^= a[i - d];
58         }
59         ans.push_back(-d);
60     }
61     for (int i = lb - 1; i >= 0; i--) {    // 在0...lb-1位中把a[i]!=b[i]的位变成b[i]
62         if (a[i] != b[i]) {
63             int d = lb - i;    // 左移lb-i位
64             for (int j = 0; j <= i; j++) {
65                 a[j] ^= a[j + d];
66             }
67             ans.push_back(d);
68         }
69     }
70     printf("%d\n", ans.size());
71     for (auto &x : ans) {
72         printf("%d ", x);
73     }
74     printf("\n");
75 }
76 
77 int main() {
78     int t;
79     scanf("%d", &t);
80     while (t--) {
81         solve();
82     }
83     
84     return 0;
85 }
复制代码

 

参考资料

  Codeforces Round #853 (Div. 2) Editorial:https://codeforces.com/blog/entry/113246

posted @   onlyblues  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-03-01 糖果传递
2022-03-01 均值不等式证明
2021-03-01 关于C++中构造函数的常见疑问
Web Analytics
点击右上角即可分享
微信分享提示