Xum题解

Xum

洛谷传送门

  • 题意:

    简化来说就是给你一个奇数 \(x\),而你只能使用 \(+\)\(\bigoplus\),让你构造出一个包含 \(1\) 的数集。

  • Analysis:

    首先为了得到 \(1\),我们一般有两种思路,第一种是构造出 \(n\)\(n+1\) 这种“出解情况”,这种思路考场寄掉了,先咕。
    那么来说说正解思路:
    对于一个数 \(x\),我们考虑它的运算集:“\(+\)”可以实现二进制数的左移操作,而 \(\bigoplus\) 本身就是二进制操作,因此,我们考虑以下转移:

    说明:未知位用a代替,设二进制数长度为 \(k\)

    \[1aaaaaaa1\tag{1} \]

    左移 \(k\) 位得:

    \[1aaaaaaa100000000\tag{2} \]

    \(1\)\(\bigoplus\) \(2\) 式得:

    \[1aaaaaaa0aaaaaaa1\tag{3} \]

    \(3\)\(+\) \(2\) 式得:

    \[1aaaaaaa10aaaaaaa1\tag{4} \]

    \(2\) 式自加后与 \(\bigoplus\) \(4\) 式得:

    \[aaaaaaa1\tag{5} \]

    \(5\)\(\bigoplus\) \(1\) 式即可得最高位:

    \[100000000\tag{6} \]

  • 实现:

    经过上述分析,我们已经实现了消去最高位,接下来只要一直循环求解下去即可。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define lowbit(x) (x&(-x))
int x;
struct Node{
    int opt,x,y;
};
vector<Node> putout;
int solve(int x){
    int y=x,ans=x>>1;
    while(ans){
        putout.push_back((Node){1,y,y});
        y<<=1;
        ans>>=1;
    }
    int z=x^y;
    putout.push_back((Node){2,x,y});
    int r=y+z;
    putout.push_back((Node){1,y,z});
    int s=y+y;
    putout.push_back((Node){1,y,y});
    int t=r^s;
    putout.push_back((Node){2,r,s});
    int u=t^x; 
    putout.push_back((Node){2,t,x});
    while(y!=lowbit(y)){
        if(y&u){
            putout.push_back((Node){2,y,u});
            y^=u;
        }
        putout.push_back((Node){1,u,u});       
        u+=u;
    }
    putout.push_back((Node){2,x,y});
    x^=y;
    return x;
}
signed main(){
    scanf("%lld",&x);
    while(x!=1) x=solve(x);
    printf("%lld\n",putout.size());
    for(int i=0;i<putout.size();i++){
        if(putout[i].opt==1) printf("1 %lld %lld\n",putout[i].x,putout[i].y);
        else if(putout[i].opt==2) printf("2 %lld %lld\n",putout[i].x,putout[i].y);
    }
    return 0;
}
posted @ 2023-07-29 21:29  Melting_Pot  阅读(24)  评论(0编辑  收藏  举报