题目大意
题目总结
问题描述
给定一个正整数 n(3≤n≤2⋅105)。你需要构造一个长度为 n 的排列 p(包含 1 到 n 的所有整数各一次),使得对于每一个 i(1≤i≤n−1),都能在索引范围 [i,n] 中找到一个下标 j(即 i≤j≤n),满足以下异或条件:
pi=pj⊕i
如果不存在满足条件的排列,则输出 −1。
输入输出
样例解释
以 n=3 为例,输出为 2 1 3:
-
当 i=1 时:需要存在 j∈{1,2,3} 使得 p1=pj⊕1。
已知 p1=2,若取 j=3,则 p3⊕1=3⊕1=2。满足条件。
-
当 i=2 时:需要存在 j∈{2,3} 使得 p2=pj⊕2。
已知 p2=1,若取 j=3,则 p3⊕2=3⊕2=1。满足条件。
-
所有 i∈[1,2] 均满足条件,故 2 1 3 是合法解。
以 n=4 为例:
- 不存在任何长度为 4 的排列能满足上述所有约束,故输出 −1。
思路讲解
这道题目,一种方法是打表找规律,比较神秘,呃,也比较费时间,只不过由于我 C1 是打表打出来的,C2 也这样子尝试了,由于选取的规律比较奇怪,在某些情况下会出现问题,后需要与下标 lowbit(n) 交换啊什么的,在这里就不介绍了。
不过可以总结一下,就是这种打表找规律的话,首先要确定没有答案的条件,其次就是写的检查器尽量报出更多的信息(在错误时),比如说这道题目,如果你构造出来的序列是错的,你写的检查器最好要报出来哪一位错了,有哪些位构造错误?这一位你填了什么值?反正信息越多越好。
那么构造方法如何解决 C1 呢?那么由于是要求 pi=pj⊕i,不妨就令 pi=i⊕1,把 1 放在最后就可以了,最后这样子生成的序列第一位可能有点问题,这个特判一下就行。
那么如果你会解决 C1 的话,其实只需要增加一行代码:
1 2 3 4 5 6
| if (N%2==0) { ans_ls[1]=N; swap(ans_ls[1],ans_ls[lowbit(N)]); }else { ans_ls[1]=N-1; }
|
即 swap(ans_ls[1],ans_ls[lowbit(N)]); 这一行代码。首先 lowbit(n)⊕1 肯定不愁找不到满足的 j,因为他都处于第一个位置了。那么对于 n 呢?那么由于 n≥n⊕lowbit(n)≥lowbit(n)+2(n 是偶数),所以说也不用愁找不到 j。
当然,注意,n 是 2 的幂次的时候是没有答案的,这也很容易理解,因为这个时候 n 无论异或上 [1,n] 中的任何一个数字,其结果都超过了 [1,n] 的范围。
AC代码
AC
https://codeforces.com/contest/2189/submission/359568527
源代码(构造)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
#include <bits/stdc++.h> #include <ranges> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<":"<<var<<"\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using LD = long double;
using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1; static constexpr ll mod = 998244353; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT;
ll lowbit(ll x) { return x&-x; }
void Solve() { ll N; cin >> N; if (has_single_bit((unsigned)N)) { cout<<-1<<"\n"; return; } vector<ll> ans_ls(N+2); for (int i=2;i<=N-1;++i) { ans_ls[i]=i^1; } ans_ls[N]=1; if (N%2==0) { ans_ls[1]=N; swap(ans_ls[1],ans_ls[lowbit(N)]); }else { ans_ls[1]=N-1; }
for (int i=1;i<=N;++i) { cout<<ans_ls[i]<<" "; } cout<<"\n";
}
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> lT; while(lT--) Solve(); return 0; }
|
AC
https://codeforces.com/contest/2189/submission/359512601
源代码(打表找规律)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
#include <bits/stdc++.h> #include <ranges> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<":"<<var<<"\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using LD = long double;
using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1; static constexpr ll mod = 998244353; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT;
ll lowbit(ll x) { return x&-x; }
void Solve() { ll N; cin >> N; if (has_single_bit((unsigned)N)) { cout<<-1<<"\n"; return; } vector<ll> ans_ls(N+2); if (N&1) { ans_ls[1]=N-1; ans_ls[N]=1; queue<ll> q_ji,q_ou; for (int i=2;i<=N-2;++i) { if (i&1) { q_ji.push(i); }else { q_ou.push(i); } } q_ji.push(N); for (int i=2;i<=N-1;++i) { if (i&1) { ll num=q_ou.front(); q_ou.pop(); ans_ls[i]=num; }else { ll num=q_ji.front(); q_ji.pop(); ans_ls[i]=num; } } }else {
auto mirror_assign=[&](ll i) { ans_ls[N+1-i]=N+1-ans_ls[i]; }; if (N%4!=0) { ans_ls[1]=N-2; ans_ls[N]=3; ans_ls[N-1]=N; ans_ls[2]=1; ans_ls[3]=N-1; ans_ls[N-2]=N+1-ans_ls[3]; ll cnt=1; vector<array<ll,2>> num_ls(N/2+2); ll idx=1; for (int i=4;i<=N;i+=2) { num_ls[idx]={i,i+1}; ++idx; } for (int i=4;i<=N/2;i+=2) { if (cnt&1) { ans_ls[i]=num_ls[cnt+1][0]; ans_ls[i+1]=num_ls[cnt+1][1]; }else{ ans_ls[i]=num_ls[cnt-1][0]; ans_ls[i+1]=num_ls[cnt-1][1]; } mirror_assign(i); mirror_assign(i+1); ++cnt; } }else {
ans_ls[1]=N-2; mirror_assign(1); ans_ls[2]=5; mirror_assign(2); ans_ls[3]=4; mirror_assign(3); ans_ls[4]=N; mirror_assign(4); ans_ls[5]=2; mirror_assign(5); ans_ls[6]=7; mirror_assign(6); ll cnt=6; for (int i=7;i<=N/2;i+=2) { ans_ls[i]=cnt; mirror_assign(i); ans_ls[i+1]=cnt+3; mirror_assign(i+1); cnt+=2; } ll lb=lowbit(N); if (lb>=8) { swap(ans_ls[4],ans_ls[8]); } if (lb>8) { swap(ans_ls[8],ans_ls[lb]); } }
} #ifndef LOCAL for (int i=1;i<=N;++i) { cout<<ans_ls[i]<<" "; } cout<<"\n"; #else bool ok_zong=true; for (int i=1;i<=N-1;++i) { bool ok=false; for (int j=i;j<=N;++j) { if ((ans_ls[j]^(i))==ans_ls[i]) { ok=true; break; } } if (!ok) { ok_zong=false; break; } } if (ok_zong) { for (int i=1;i<=N;++i) { cout<<ans_ls[i]<<" "; } cout<<"\n"; return; } cout<<"WA:"; for (int i=1;i<=N;++i) { cout<<ans_ls[i]<<" "; if (i==N/2) { cout<<"| "; } } cout<<"\n"; #endif }
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> lT; while(lT--) Solve(); return 0; }
|
打表程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
#include <bits/stdc++.h> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<":"<<var<<"\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using LD = long double;
using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1; static constexpr ll mod = 998244353; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT;
void Solve() { ll N; cin >> N; vector<char> used(N+2); vector<ll> P(N+2); ll cnt=0; auto dfs=[&](auto && self,ll idx) { if (idx==N) { ++cnt; P[N]=3; for (int i=1;i<=N;++i) { cout<<P[i]<<" "; if (i==N/2) cout<<"| "; } cout<<"\n"; return; } if (idx<=N/2) { for (int v=1;v<=N;++v) { if (idx==1 && v!=N-2) continue; if (used[v]) continue; ll target=v^idx; if (target>=1 && target<=N && !used[target]) { used[v]=true; P[idx]=v; self(self,idx+1); used[v]=false; } } }else { for (int v=N+1-P[N+1-idx];v<=N+1-P[N+1-idx];++v) { if (used[v]) continue; ll target=v^idx; if (target>=1 && target<=N && !used[target]) { used[v]=true; P[idx]=v; self(self,idx+1); used[v]=false; } } }
}; dfs(dfs,1); cout<<N<<" "<<"一共输出了 "<<cnt<<" 个序列\n"; cout<<"\n---------------------------------\n"; }
signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> lT; while(lT--) Solve(); return 0; }
|
心路历程(WA,TLE,MLE……)