Serval and Shift-Shift-Shift

有趣的构造题。

考虑到两个字符串最多有 nn 位不同,而我们最多只能操作一次,不难想到每次操作修改一位,且不影响之前已经操作过的位。

一个数异或 00 不变,所以可以想到不影响之前操作的位等价于将那些数异或上 00

接着考虑左移和右移如何构造出 00?可以发现左移时,后缀的一段自动补 00。右移时,前缀一段自动补 00。我们找到两个字符串最靠左的 11,设为 xxyy

如果 x=yx=y,我们从 x+1x+1 扫到 nn,只要有不同的就通过右移的方式把 xx 点的 11 挪过去,前缀不变。

如果 x>yx>y,先左移一次,让 sx=1s_x=1,然后按照 x=yx=y 做。

如果 x<yx<y,先按照 x=yx=y 做,最后只有 sxs_xsys_y 不同。用 ss 中最靠右的 11 一直左移直到把这个 xx 点的 11 推出去即可。

当两个字符串一个全 00 另一个非全 00 时无解。

#include <bits/stdc++.h>
using namespace std;

const int N = 2e3 + 5;

int t, n, x, y;
string a, b;
vector<int> ans;

void op(string& s, int k)
{
    if (!k) return;
    ans.emplace_back(k);
    string g;
    for (int i = 0; i <= n; i++) g += "0";
    for (int i = 1; i <= n; i++)
    {
        if (i - k >= 1 and i - k <= n) g[i - k] = s[i];
    }
    for (int i = 1; i <= n; i++)
    {
        if (g[i] - '0')
        {
            s[i] = ((s[i] - '0') xor 1) + '0';
        }
    }
}

void pre()
{
    op(a, x - y);
    x = y;
}

void solve()
{
   for (int i = x + 1; i <= n; i++)
   {
       if (a[i] != b[i])
       {
            op(a, -i + x);
       }
   }
}

void solve2()
{
    int lpos = n;
    for (int i = n; i >= 1; i--)
    {
        if (a[i] - '0')
        {
            lpos = i;
            break;
        }
    }
    for (int i = x; i >= 1; i--)
    {
        if (a[i] != b[i])
        {
            op(a, lpos - i);   
        }
    }
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> t;
    while (t--)
    {
        cin >> n;
        cin >> a >> b;
        a = " " + a, b = " " + b;
        ans.clear();
        x = 0, y = 0;
        for (int i = 1; i <= n; i++)
        {
            if (!x and a[i] == '1') x = i;
            if (!y and b[i] == '1') y = i;
        }
        if (x and !y) cout << "-1\n";
        else if (!x and y) cout << "-1\n";
        else if (a == b) cout << "0\n";
        else
        {
            if (x > y) pre();
            solve();
            if (x < y) solve2();
            cout << ans.size() << "\n";
            for (auto &i : ans) cout << i << " ";
            cout << "\n";
        }
    }
    return 0;
}
posted @   HappyBobb  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示