本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
【Codeforces】Codeforces Round #836 (Div. 2) C. Almost All Multiples | 贪心
题目链接
题目
Given two integers n and x, a permutation p of length n is called funny if is a multiple of i for all , and .
Find the lexicographically minimal funny permutation, or report that no such permutation exists.
A permutation of length n is an array consisting of each of the integers from 1 to n exactly once.
Let a and b be permutations of length n. Then a is lexicographically smaller than b if in the first position i where a and b differ, . A permutation is lexicographically minimal if it is lexicographically smaller than all other permutations.
题目大意
给定两个整数 和 ,一个有趣的排列 需要满足以下条件:
- 对于 , 是 的倍数。
- 。
- 。
如果对于给定的 和 ,存在满足上述条件的有序排列,则输出其中字典序最小的那一个。否则报告不存在这样的排列。
排列:长度为 且其中从 到 的每一个整数恰好出现一次。
字典序:设 和 是长度为 的排列,则如果在 和 不同的第一位置 上,有 ,则 的字典序小于 。如果一个排列的字典序小于所有其他排列,则它字典序最小。
思路
最初我们令 时,满足对于 , 是 的倍数,且字典序是所有排列中最小的。我们让 后,容易发现如果 不是 的倍数,一定不可能找到一个位置 ,满足:
- 是 的因数, 可以放在 。
- 是 的倍数, 可以放在 。
所以我们报告无解。
如果 ,我们可以首先令 ,然后试图把 向后移。遍历后续数组,一旦存在位置 满足 ,就交换 和 ,并令 试图让 继续后移。
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <map>
#include <vector>
#include <string.h>
#include <queue>
using namespace std;
using LL=long long;
const int N=500001;
const LL mod=1000000007;
int n,m,k,x,y,z,tot,a[N],b[N];
char ch[N];
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
LL solve()
{
scanf("%d",&n);
scanf("%d",&k);
if (n%k) return printf("-1\n");
for (int i=1;i<=n;++i) a[i]=i;
a[1]=k;
a[k]=n;
a[n]=1;
for (int i=k+1;i<n;++i)
{
if (n%i==0&&i%k==0)
{
a[k]=i;
a[i]=n;
k=i;
}
}
for (int i=1;i<=n;++i) printf("%d ",a[i]);
printf("\n");
return 0;
}
int main()
{
int T=1;
scanf("%d",&T);
while (T--) solve();
return 0;
}