3764. 三元数异或

AcWing 3764. 三元数异或

题目:

如果一个整数,其各个数位不包含 0,1,2 以外的数字,则称这个数为三元数。

例如,1022,11,21,2002 都是三元数。

给定一个可能很长的三元数 x,其首位数字(最左边那位)保证为 2,其他位数字为 0 或 1 或 2。

我们规定,两个长度为 n 的三元数 a 和 b 可以通过三元异或运算 ⊙ 得到另一个长度为 n 的三元数 c。

设 ai,bi,ci 分别表示 a,b,c 的第 i 位的数字,则 ci=(ai+bi)mod3。

例如,10222 ⊙ 11021=21210。

你的任务是对于每个给定的 x,求出可以满足 a ⊙ b=x,并且 max(a,b) 尽可能小的 a,b。

注意,a,b 都必须是 n 位三元数,且不含前导 0。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含整数 n,表示 x 的长度。

第二行包含一个长度为 n,首位为 2 的三元数 x。

输出格式
每组数据输出占两行,分别包含数 a 和数 b。

如果答案不唯一,则输出任意合理答案均可。

数据范围
1≤T≤104,
1≤n≤5×104,
同一测试点所有 n 的和不超过 5×104。

输入样例:
4
5
22222
5
21211
1
2
9
220222021
输出样例:
11111
11111
11000
10211
1
1
110111011
110111010

思路:

1. 给出三元数c, 求满足条件的三元数 a,b
2. 三元异或运算 a ⊙ b = (a+b)%3;
3. 使a ⊙ b==c 且满足max(a,b)尽可能的小,意思是a,b中的最大值要在所有满足条件的答案中较小
4. 三元数定义:一个整数,其各个数位不包含 0,1,2 以外的数字,则称这个数为三元数
   分析三元数的每一位可以由哪两个数经过三元异或运算得出:
    ①.0可以由(0,0)、(1,2)
    ②.1可以由(0,1)、(2,2)
    ③.2可以由(0,2)、(1,1)经过三元异或运算得出
又因为需要满足max(a,b)的结果尽可能小,则a和b中的较大值要尽可能的小,故用贪心

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

const int N = 5e4+5;
char a[N], b[N], c[N];

int main()
{
    int T;
    cin>>T;
    while (T--)
    {
        int n, i;
        cin>>n;
        memset(a,0,sizeof(char)*n);
        memset(b,0,sizeof(char)*n);
        memset(c,0,sizeof(char)*n);
        cin>>c;
        a[0] = b[0] = '1';//c的首位数一定为2,那么a和b的首位一定为1
        int isBMax = 0;//标记当前b是否已经比a大
        for (i = 1; i < n; i++)
            if(c[i] == '0')//0,0
                a[i] = b[i] = '0';
            else if (c[i] == '1')//0,1
            {
                if (isBMax)//如果当前b已经为a,b中较大值,则只需要令b在满足条件的答案中不再继续变大即可
                    a[i] = '1', b[i] = '0';
                else
                    a[i] = '0', b[i] = '1';
                isBMax = 1;//标记当前b已经为a,b中的较大值
            }
            else if (c[i] == '2')//0,2  1,1
                if (isBMax)//如果当前b已经为a,b中较大值,则只需要令b在满足条件的答案中不再继续变大即可
                    a[i] = '2', b[i] = '0';
                else
                    a[i] = b[i] = '1';

        a[n] = b[n] = '\0';//添上结尾符
        cout<<a<<endl<<b<<endl;//输出a,b
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值