[ICPC 2024 Kunming I] 乐观向上题解

题目描述

求字典序最小的序列 p0​,p1​,p2​⋯,pn−1​,该序列是 0,1,2,⋯,(n−1) 的一个排列,且满足以下限制:对于所有 0≤i<n,都有 p0​⊕p1​⊕⋯⊕pi​>0。这里 ⊕ 是按位异或运算。

称一个长度为 n 的序列 p0​,p1​,⋯,pn−1​ 的字典序小于另一个长度为 n 的序列 q0​,q1​,⋯,qn−1​,若存在一个整数 0≤k<n 使得对于所有 0≤i<k 有 pi​=qi​,以及 pk​<qk​。

输入格式

有多组测试数据。第一行输入一个整数 T 表示测试数据组数。对于每组测试数据:

第一行输入一个整数 n(1≤n≤106)。

保证所有数据 n 之和不超过 106。

输出格式

每组数据输出一行 n 个由单个空格分隔的整数,表示字典序最小的且满足限制的排列。如果不存在这种排列,输出 impossible。

输入输出样例

输入 #1复制

4
1
2
3
4

输出 #1复制

impossible
1 0
1 0 2
impossible

思路

贪心。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long t,n,k,a[1000006],m,b[1000006],c[1000006],d[1000006],lk=0,sd=0;
int main(){
	cin>>t;
    while(t--){
        cin>>n;
        if(n!=1){
            for(int i=0;i<=n-1;i++){
                b[i]=0;
                c[i]=i+1;
                d[i]=i-1;
                a[i]=-1;
            }
            sd=0;
            a[n]=-1;
            d[0]=0;
            a[1]=1;
            b[1]=1;
            c[0]=2;
            d[2]=0;
            lk=1;
            for(int i=2;i<=n;i++){
                for(int j=0;j<=n-1;j=c[j]){
                    if(j!=lk&&b[j]==0){
                        a[i]=j;
                        lk^=j;
                        c[d[j]]=c[j];
                        d[c[j]]=d[j];
                        b[j]=1;
                        break;
                    }
                }
                if(a[i]==-1){
                    sd=1;
                    break;
                }
            }
            if(sd==1){
                cout<<"impossible"<<endl;
            }
            else{
                for(int i=1;i<=n;i++){
                    cout<<a[i]<<" ";
                }
                cout<<endl;
                //break;
            }            
        }
        else{
            cout<<"impossible"<<endl;
        }
    }
	return 0;
}

posted @ 2025-10-14 19:38  bz02_2023f2  阅读(14)  评论(0)    收藏  举报  来源