2021牛客寒假集训营第一场-I限制不互素对的排列
I限制不互素对的排列
链接:https://ac.nowcoder.com/acm/contest/9981/I
来源:牛客网
题目描述
输入一个数
,请构造一个长度为
的排列,使得其中正好有
对相邻的数gcd(最大公约数)大于
。
排列是指
到
一共
个数,每个数都出现过且仅出现过
次。例如,
是一个排列,而
、
则不是排列
排列是指
输入描述:
两个整数
和
,用空格隔开。
输出描述:
如果不存在可行的构造方案,输出-1。
否则输出一行
个数,用空格隔开。如果有多组可行的构造方案,输出任意一组即可。
解体思路
比赛当时没找到规律,其实找到了正确的思路这道题就很简单。因为0<=k<=n/2,而在小于等于n的范围内,有n/2(向下取整)个偶数,将这些偶数排列在一起,就至少有n/2-1对数使得gcd不等于1。
所以分两种情况,一类k<n/2,一类k=n/2。
在前一类里,只需要把k+1个偶数排在前面,后面用剩下的数补满即可。
对于第二类情况,前面用除6以外的偶数不满,后面跟上 6 3 ,再用剩余的奇数补齐。这样由于6 3这一对数的存在,满足了第n/2对的需求。
特殊情况:由于第二种情况里需要6来满足第n/2对的非互质数对,所以当n<6时,k=n/2无解。
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[100010]; 4 int main() 5 { 6 ios::sync_with_stdio(false); 7 cin.tie(0); 8 int n, k; 9 cin >> n >> k; 10 if (n <= 5) 11 { 12 if (k >= n / 2) 13 { 14 cout << "-1\n"; 15 return 0; 16 } 17 else 18 { 19 for (int i = 1; i <= k + 1; i++) 20 { 21 cout << i * 2 << " "; 22 a[i * 2] = 1; 23 } 24 for (int i = 1; i <= n; i++) 25 { 26 if (a[i] != 1) 27 cout << i << " "; 28 } 29 } 30 } 31 else 32 { 33 if (k == n / 2) 34 { 35 for (int i = 2; i <= n; i += 2) 36 { 37 if (i != 6) 38 { 39 cout << i << " "; 40 a[i] = 1; 41 } 42 } 43 cout << "6 3 "; 44 a[6] = a[3] = 1; 45 for (int i = 1; i <= n; i++) 46 { 47 if (a[i] != 1) 48 cout << i << " "; 49 } 50 } 51 else 52 { 53 for (int i = 1; i <= k + 1; i++) 54 { 55 cout << i * 2 << " "; 56 a[i * 2] = 1; 57 } 58 for (int i = 1; i <= n; i++) 59 { 60 if (a[i] != 1) 61 cout << i << " "; 62 } 63 } 64 } 65 return 0; 66 }

浙公网安备 33010602011771号