AtCoder Regular Contest 144

C - K Derangement

https://atcoder.jp/contests/arc144/tasks/arc144_c

Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 600 points

Problem Statement

You are given positive integers N and K. Find the lexicographically smallest permutation A=(A1,A2,,AN) of the integers from 1 through N that satisfies the following condition:

  • |Aii|K for all i (1iN).

If there is no such permutation, print -1.

Constraints

  • 2N3×105
  • 1KN1

Input

Input is given from Standard Input in the following format:

N K

Output

Print the lexicographically smallest permutation A=(A1,A2,,AN) of the integers from 1 through N that satisfies the condition, in the following format:

A1 A2 AN

If there is no such permutation, print -1.


Sample Input 1

3 1

Sample Output 1

2 3 1

Two permutations satisfy the condition: (2,3,1) and (3,1,2). For instance, the following holds for (2,3,1):

  • |A11|=1K
  • |A22|=1K
  • |A33|=2K

Sample Input 2

8 3

Sample Output 2

4 5 6 7 8 1 2 3

Sample Input 3

8 6

Sample Output 3

-1

解题笔记

首先需要找到存在这种排列的必要条件,即 N2K。因为第 K 位要么取 KK=0,要么取 K+K=2K,由于 0 不符合题意,则第 K 位必须取 2K。要满足这个条件,必须有 N2K

接下来的重点就是找到通项公式。分为四种情况:

  • N<2K: 无解
  • 2KN3K:

    A(i)={i+K(1iNK)iN+K(NK<iN)

  • 3K<N4K:

    A(i)={i+K(1iK)iK(K<iN2K)i+K(N2K<iNK)i2K(NK<i3K)iK(3K<iN)

  • 4K<N:

    A(i)={i+K(1iK)iK(K<i2K)A(i)(2K<iN)

    这个意思是前 2K 位为 (K+1,,2K,1,,K),剩余的部分的 N=N2K,再选择符合 N 大小的公式。不断使用情况四的公式进行递推,一定可以转化为情况二或情况三。

代码

#include <bits/stdc++.h>

using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N, K;
    cin >> N >> K;
    if (2 * K > N)
    {
        cout << -1 << endl;
        return 0;
    }
    int cnt = 0;
    while (N - cnt >= 4 * K)
    {
        for (int i = 1; i <= K; i++)
            cout << cnt + i + K << ' ';
        for (int i = 1; i <= K; i++)
            cout << cnt + i << ' ';
        cnt += 2 * K;
    }
    if (N - cnt <= 3 * K)
    {
        int i = 1;
        for (; i <= (N - cnt) - K; i++)
            cout << i + K + cnt << ' ';
        for (; i <= (N - cnt); i++)
            cout << i - (N - cnt) + K + cnt << ' ';
    }
    else
    {
        int i = 1;
        for (; i <= K; i++)
            cout << i + K + cnt << ' ';
        for (; i <= (N - cnt) - 2 * K; i++)
            cout << i - K + cnt << ' ';
        for (; i <= (N - cnt) - K; i++)
            cout << i + K + cnt << ' ';
        for (; i <= 3 * K; i++)
            cout << i - 2 * K + cnt << ' ';
        for (; i <= (N - cnt); i++)
            cout << i - K + cnt << ' ';
    }
    cout << endl;
    return 0;
}