自学内容网 自学内容网

2024HNCPC G - Utakotoba

直接贴码了,注释可能有误,欢迎指出

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


/*
注意掉操作过程其实是可逆的
swap有一种方法就是x=x^y y = x^y x = x^y,灵感来源?
所以说其实a,b数组是由基向量生成出来的,如果a数组可以变成b数组,那么他们的基向量得是等价的,既然是等价的必然可以相互转化
所以有了构造思路就是把数组变成同一组0000+基向量的形式
那么答案就是a变成基的正向过程+b变成基的逆向过程

details: 
(1)对两个不同位置的数操作其实就是把一个数swap到另一个数旁边异或一下,再swap回去
*/
int n;
inline void solve(){
    cin>>n;
    vector<int>c(n+1),b(n+1);
    for(int i = 1;i<=n;++i) cin>>b[i];
    for(int i = 1;i<=n;++i) cin>>c[i];
    auto get=[&](vector<int> &a)->vector<pair<int,int>>{
        vector<int> base(20),pos(20,-1),ff(n+1,-1);//基,基的位置,位置的基(逆映射)
        vector<pair<int,int>> op;
        auto swp=[&](int x,int y)->void{
            op.push_back({x,y});
            op.push_back({y,x});
            op.push_back({x,y});
        };
        auto insert=[&](int x,int po)->void{
            for(int i = 15;i>=0;--i){
                if(!((x>>i)&1)) continue;
                if(!base[i]){
                    base[i] = x;
                    pos[i]=po;
                    ff[po]=i;
                    break;
                }else x^=base[i];
            }
        };

        auto XOR=[&](int l,int r)->void{
            if(l<=r){
                for(int i = l+1;i<=r-1;++i) swp(i,i-1);
                op.push_back({r-1,r});
                for(int i = r-2;i>=l;--i) swp(i,i+1);
            }else{
                for(int i = r;i<=l-2;++i) swp(i,i+1);
                op.push_back({l,l-1});
                for(int i = l-1;i>r;--i) swp(i,i-1);
            }
        };

        //插入线性基
        for(int i = 1;i<=n;++i) insert(a[i],i);

        //将线性基从高位到低位提前
        int l = 0;//目前基的个数
        for(int i = 14;i>=0;--i){
            if(!base[i]) continue;
            ++l;
            for(int j = pos[i];j>l;--j){
                if(ff[j]!=-1) pos[ff[j]]=j-1;
                if(ff[j-1]!=-1) pos[ff[j-1]]=j;
                swap(ff[j],ff[j-1]);
                swap(a[j],a[j-1]);
                swp(j,j-1);
            }
        }

        //构造线性基,类似于高等代数里面的化成阶梯型
        /*
        1 1 0 0 1    (1)
        1 0 1 0 0    (2)
        0 1 1 1 0    (3)
        1 0 0 1 0    (4)
        0 0 0 1 1    (5)
        
        先把第一列第一行下面的1全消掉
        先把第二列第二行下面的1全消掉
        ...
        */
        //整个过程是看i这个可以变成基向量元素前面不应该是1的位置把它处理掉
        for(int i = 1;i<=l;++i){//从高位到低位处理
            for(int j = 14;j>=0;--j){//从高位到低位处理
                if(pos[j]==i) break;
                if(base[j]&&((a[i]>>j)&1)){
                    a[i]^=base[j];
                    XOR(i,pos[j]);
                }
            }
        }
        //化成最简形式,类似于把阶梯型矩阵化成行最简形式
        //把第i行第j列上下的1全部消掉,因为已经是阶梯型,所以只有那些基里的1要消了
        for(int i = 14;i>=0;--i){
            for(int j = i-1;j>=0;--j){
                if(base[j]&&(base[i]>>j)&1){
                    a[pos[i]]^=base[j];
                    base[i]^=base[j];
                    XOR(pos[i],pos[j]);
                }
            }
        }
        //把最前面的L个线性基换到最后面,将后面经过的全部位置变成0
        for(int i = l,r=0;i>=1;--i,++r){
            for(int j = i;j<n-r;++j){
                swp(j,j+1);
                swap(a[j],a[j+1]);
                int now = a[j];
                for(int k = 14;k>=0;--k){
                    if(base[k]&&(now>>k&1)){
                        now^=base[k];
                        if(pos[k]==i){//刚好用的是当前这个异或操作且需要异或
                            a[j]^=base[k];
                            op.push_back({j,j+1});
                        }
                    }
                }
            }
        }
        return op;
    };
    vector<pair<int,int>>op1 = get(b);
    vector<pair<int,int>>op2 = get(c);
    reverse(op2.begin(),op2.end());
    cout<<op1.size()+op2.size()<<"\n";
    for(auto i:op1) cout<<i.first<<" "<<i.second<<"\n";
    for(auto i:op2) cout<<i.first<<" "<<i.second<<"\n";
}

signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t=1;
    //cin>>t;
    while(t--){
        solve();
    }
    return 0;
}




原文地址:https://blog.csdn.net/theskyinblue/article/details/143695628

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!