Codeforces Round #640 (Div. 4) G. Special Permutation
May 14, 2020
問題
数値n (>= 2)
が与えられるので、1~n
までの数列を作れ
条件として、数列のi
番目とi+1
番目の差の絶対値が2以上4以下
であること
作れない場合は-1
を出力し、作れる場合は実際にそれを表示すること
考えたこと
小さい数値で実際に作ってみる
n == 2,3
の場合はどんなに頑張っても作れないn == 4
の場合は{2,4,1,3}
で作れるn == 5
の場合は{1,3,5,2,4}
n == 6
の場合は{1,4,2,6,3,5}
n == 7
の場合は{1,4,2,5,7,3,6}
n == 8
の場合は{2,4,1,3,6,8,5,7}
これをみると、n==4
のパターンが繰り返せそうに見える
実際にn==8
は{2,4,1,3,2+4,4+4,1+4,3+4}
とも言える
あらかじめn=4~7
のパターンを定義しておいて、以下のように場合分けすればいけそう
n == 2,3
の場合は-1
を出力n < 8
の場合は上記のパターンを出力n >= 8
の場合は、div = n/4
とrem = n%4
の値を求めておき,n==4
のパターンをdiv-1
回繰り返した後に、最後の1パターンをn == rem+4
のパターンで作れば良さそう
あとはこれを実装する
実装
int main() {
vector<vector<int>> ptn(10);
ptn[4] = {2,4,1,3};
ptn[5] = {1,3,5,2,4};
ptn[6] = {1,4,2,6,3,5};
ptn[7] = {1,4,2,5,7,3,6};
int t; cin >> t;
rep(_, t) {
int n; cin >> n;
if(n == 2 || n == 3) {
cout << -1;
} else if(n < 8) {
rep(i, ptn[n].size()) {
cout << ptn[n][i];
if(i != ptn[n].size()-1) cout << " ";
}
} else {
int rem = n % 4;
int div = n / 4;
int now = 0;
rep(__, div-1) {
rep(i, 4) {
cout << ptn[4][i] + now << " ";
}
now += 4;
}
rep(i, ptn[rem+4].size()) {
cout << ptn[rem+4][i] + now;
if(i != ptn[rem+4].size()-1) cout << " ";
}
}
cout << endl;
}
return 0;
}