牛客周赛 Round 105【D题:重排构造题解】
📖 题目描述
给定一个长度为 n 的数组,数组中只包含整数 1 和 2。要求重新排列数组,使得相邻元素的最大公因数之和等于给定值 k。
输入格式:
-
📥 第一行:两个整数
n, k -
📥 第二行:
n个整数,每个都是1或2
输出格式:
-
❌ 如果无解,输出
-1 -
✅ 否则输出任意一个满足条件的重排数组
💡 解题思路
相邻两个数的最大公因数:
-
gcd(1,1) = 1 -
gcd(1,2) = 1 -
gcd(2,1) = 1 -
gcd(2,2) = 2
👉 只有两个 2 相邻时贡献为 2,其他情况都贡献 1
📐 数学构造
设数组中有 x 对相邻的 2,则:
-
这
x对的贡献:x × 2 = 2x -
剩余
(n-1-x)对的贡献:(n-1-x) × 1 -
总和 =
2x + (n-1-x) = n-1+x
要求:
\(n−1+x=k⇒x=k−(n−1)\)
🛠️ 算法设计
根据 x 的值分两种情况处理:
🎯 情况1:x = 0(不需要相邻的2)
-
条件检查:所有
2都不能相邻 →b ≤ a+1 -
构造策略:交替排列
1 2 1 2 1 2...或者2 1 2 1 2 1...
if (x==0) {
if (b>a+1) {
cout<<"-1"<<endl;
return 0;
}
//如果2的数量更多,构造2 1 2 1 2 1...
if (b>=a) {
for (int i=0;i<a;i++)
cout<<"2 1 ";
for (int i=0;i<b-a;i++)
cout<<"2 ";
}
//1的数量更多,构造1 2 1 2 1 2 ...
else {
for (int i=0;i<b;i++)
cout<<"1 2 ";
for (int i=0;i<a-b;i++)
cout<<"1 ";
}
}
🎯 情况2:x > 0(需要恰好 x 对相邻的2)
-
条件检查:
-
需要至少
x+1个2来形成x对相邻的2 -
需要足够的
1来分隔剩余的2
-
-
构造策略:
-
先放置
x+1个连续的2 -
用
1分隔剩余的2:1 2 1 2... -
最后放置剩余的
1
-
else {
int bb=b-(x+1);
if (a<bb) {
cout<<"-1"<<endl;
return 0;
}
//先放置 x+1 个连续的 2
for (int i=0;i<x+1;i++)
cout<<"2 ";
//用 1 分隔剩余的 2
for (int i=0;i<bb;i++)
cout<<"1 2 ";
//放置剩余的 1
for (int i=0;i<a-bb;i++)
cout<<"1 ";
}
🖥 C++ 实现
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
int main() {
int n,k;
cin>>n>>k;
int a=0;
int b=0;
for(int i=1;i<=n;i++) {
int x;
cin>>x;
if (x==1)
a++;
else if (x==2)
b++;
}
int x=k-(n-1);
if (x<0||x>=b) {
cout<<"-1"<<endl;
return 0;
}
if (x==0) {
if (b>a+1) {
cout<<"-1"<<endl;
return 0;
}
if (b>=a) {
for (int i=0;i<a;i++)
cout<<"2 1 ";
for (int i=0;i<b-a;i++)
cout<<"2 ";
}
else {
for (int i=0;i<b;i++)
cout<<"1 2 ";
for (int i=0;i<a-b;i++)
cout<<"1 ";
}
}
else {
int bb=b-(x+1);
if (a<bb) {
cout<<"-1"<<endl;
return 0;
}
for (int i=0;i<x+1;i++)
cout<<"2 ";
for (int i=0;i<bb;i++)
cout<<"1 2 ";
for (int i=0;i<a-bb;i++)
cout<<"1 ";
}
cout<<endl;
return 0;
}
📊 复杂度分析
-
⏱ 时间复杂度:
O(n)(输入输出) -
💾 空间复杂度:
O(1)(常数额外空间)
🎯 总结
题目的样例有点不太全,我的第一次代码
输入:n=7, k=6, [1 1 1 2 2 2 2]
输出:1 2 1 2 1 2 2
但是这个的gcd和值为7;
正确的输入应该是: 2 1 2 1 2 1 2
明显错误,但是ac了。
后面我就在x = 0的判断里,又加了两个判断,判断是应该先输出 1 还是 2。

浙公网安备 33010602011771号