Codeforces Round #463 C. Permutation Cycle

For a permutation P[1… N] of integers from 1 to N, function f is defined as follows:
这里写图片描述
Let g(i) be the minimum positive integer j such that f(i, j) = i. We can show such j always exists.
For given N, A, B, find a permutation P of integers from 1 to N such that for 1 ≤ i ≤ N, g(i) equals either A or B.
Input
The only line contains three integers N, A, B (1 ≤ N ≤ 106, 1 ≤ A, B ≤ N).
Output
If no such permutation exists, output -1. Otherwise, output a permutation of integers from 1 to N.
Example
Input
9 2 5
Output
6 5 8 3 4 1 9 2 7
Input
3 2 1
Output
1 2 3
Note
In the first example, g(1) = g(6) = g(7) = g(9) = 2 and g(2) = g(3) = g(4) = g(5) = g(8) = 5
In the second example, g(1) = g(2) = g(3) = 1

题意:
P是一个排列,P[i]是第i位上的数字,例如:n=3,那么P={1,3,2},P[2]=3,P[3]=2。
给一个函数f(i, j):代入一个i,j,当j > 1时,将i所对应的位置的值P[i]代入,同时j - 1,直到j==1,返回p[i]的值。
例如:一个排列P={2,3,4,5,1},f(2,4)=f(3,3)=f(4,2)=f(5,1)=5。
接着定义一个函数g:对于每一个i,g(i)的值是f(i,j)=i的最小一个j。现在给你n,a,b,让你构造一个排列P,对于每一个i,使g(i)==a或b。

思路:

  • 函数f很简单,其实就是一个位置转移的过程(图中节点的转移),当j==1时返回当前位置的里的值。当前节点是i,那么下一个就是P[i],接下来呢 重复刚刚的操作即可。
  • 重点是函数g:f(i,j)=i,我把函数f的意义和图的节点遍历联系起来 :就是以i为起点,经过不断的转移又回到i,那么转移次数就是j的大小啊,所以j最小,就是让我们构造一个环,j就是这个环的最小正周期。
  • 接着推构造的规律:1的环1->1 ,2的环2->1 3的环2->3->1 4的环2->3->4->1,构造方式很明显了,将1-n的升序排列整体向左平移一次,第一个位置放到最后位置去即可。注意,环不一定有一个,比如样例1,由于我们的排列元素不能重复,所以会产生无解的情况,此时就是环的个数无法正确的得到。
  • 关于环的个数,利用扩展欧几里得或者暴力枚举即可解出ax+by=n这个不定方程的一组非负整数解,就可以构造了,其中x,y所对应的值即周期为a的环x个,周期为b的环y个,且利用的元素不能重复。

代码如下:

#include <stdio.h>

int main()
{
    int n, a, b;
    scanf("%d%d%d", &n, &a, &b);
    int flag = 0, x, y;
    for(int i = 0; i <= n; i++)
    {
        int tmp = n - a * i;
        if(tmp < 0)//注意枚举时要注意剪枝,否则会超时
            break;
        if(tmp % b == 0)
        {
            flag = 1;
            x = i;
            y = tmp / b;
            break;
        }
    }
    if(flag == 0)
    {
        printf("-1\n");
    }
    else
    {
        int cur = 1;
        for(int i = 1; i <= x; i++)
        {
            for(int j = cur + 1; j < cur + a; j++)
                printf("%d ", j);
            printf("%d ", cur);
            cur += a;
        }
        for(int i = 1; i <= y; i++)
        {
            for(int j = cur + 1; j < cur + b; j++)
                printf("%d ", j);
            printf("%d ", cur);
            cur += b;
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/floraqiu/article/details/79600789