第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京)K Co-prime Permutation

本文介绍了一种特殊的排列——kk共质排列,并提供了解决方案。对于长度为n的排列,寻找恰好有k个元素与它们的位置互质的方法。通过调整元素位置确保满足条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Kotori is very good at math (really?) and she loves playing with permutations and primes.

One day, she thinks of a special kind of permutation named kk co-prime permutation. A permutation p1,p2,⋯ ,pnp_1,p_2,\cdots,p_np1,p2,,pn


of nn is called a kk co-prime permutation of nn if there exists exactly kk integers ii such that 1≤i≤n1≤i≤n,andgcd(pi,i)=1,gcd(pi,i)=1,where,gcd(x,y)gcd(x,y)1 \le i \le n1≤i≤n ,and \text{gcd}(p_i,i)=1,gcd(p i,i)=1, where, \text{gcd}(x,y)gcd(x,y)1in1in,andgcd(pi,i)=1,gcd(pi,i)=1,where,gcd(x,y)gcd(x,y) indicates the greatest common divisor of xx and yy.

Given nn and kk, please help Kotori construct a kk co-prime permutation of nn or just report that there is no such permutation.

Recall that a permutation of nn is a sequence of length nn containing all integers from 11 to nn.
输入描述:
There is only one test case in each test file.

The first and only line contains two integers nn and kk (1≤n≤106,1≤n≤106,0≤k≤n,0≤k≤n).(1 \le n \le 10^6,1≤n≤10^6 , 0 \le k \le n ,0≤k≤n).(1n106,1n106,0kn,0kn).
输出描述:
Output one line containing nn integers p1,p2,⋯ ,pnp_1, p_2, \cdots, p_np1,p2,,pn

separated by one space, indicating the permutation satisfying the given constraints. If no such permutation exists output “-1” (without quotes) instead. If there are multiple valid answers you can print any of them.

Please, DO NOT output extra spaces at the end of each line, otherwise your answer may be considered incorrect!
示例1
输入
5 3
输出
1 4 5 2 3
示例2
输入
1 0
输出
-1

题意

给定一个长度为n的数列和k,让求出一个gcd(a[i],i)=1gcd(a[i],i)=1gcd(a[i],i)=1 个数等于k的排列

思路

尝试多写几组样例可得
5 0
-1
5 1
1 2 3 4 5
1 2 3 4 5

5 2
2 1 3 4 5
1 2 3 4 5

5 3
1 2 3 5 4
1 2 3 4 5

5 4
2 1 4 3 5
1 2 3 4 5

5 5
5 1 2 3 4
1 2 3 4 5

k=0的时候无解,因为1和1互质
其他情况都有解
k是奇数的时候从非1的数里面两两调换,这样就可以多出来偶数对gcd(a[i],i)=1gcd(a[i],i)=1gcd(a[i],i)=1
k是奇数的时候从1开始的数里面两两调换,这样就可以多出来奇数对gcd(a[i],i)=1gcd(a[i],i)=1gcd(a[i],i)=1

代码

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1000000+100;
int a[maxn];
int main()
{
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++) a[i] = i;
	if(k==0) return cout<<-1,0;
	else
	{
		if(k==1)
		{
			for(int i=1;i<=n;i++)
			cout<<i<<" ";
		}
		else if(k==n)
		{
			cout<<n<<" ";
			for(int i=1;i<=n-1;i++)
			cout<<i<<" ";
		}
		else
		{
			if(k%2==0)
			{
				int now = k/2;
				int f = 1;
				int cnt = 0;
				for(int i=1;i<=n;i++)
				{
					if(now)
					{
						cnt++;
						if(f)
						cout<<i+1<<" " , f = !f; 
						else
						cout<<i-1<<" " , f = !f;
						if(cnt==2) now-- , cnt = 0;
					}
					else
					cout<<i<<" ";
				}	
			}
			else
			{
				a[1] = 1;
				for(int i=2;i<=k;i+=2)
				{
					a[i] = i+1;
					a[i+1] = i;
				}
				for(int i=1;i<=n;i++) cout<<a[i]<<" ";
			}
		}
	} 
}

/*
5 0 
-1
5 1
1 2 3 4 5
1 2 3 4 5

5 2
2 1 3 4 5
1 2 3 4 5

5 3
1 2 3 5 4
1 2 3 4 5 

5 4
2 1 4 3 5
1 2 3 4 5

5 5
5 1 2 3 4
1 2 3 4 5
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值