明天周末!!!
一、基础题
题目:小红的小小红
思路
先把目标子串输出,然后记录下字符串的所有字符数量并减去已经输出了的字符数量,剩下的直接输出即可
代码
cpp
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ff first
#define ss second
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
string s;
cin >> s;
map<char, int>v;
for (auto i : s)
{
v[i]++;
}
string s1 = "xiaohong";
for (auto i : s1)
{
v[i]--;
}
cout << s1;
for (auto i : v)
{
for (int j = 1; j <= i.ss; j++)
{
cout << i.ff;
}
}
}
二、提高题
题目:小红构造数组
思路
我们可以先把所有质因数找出来,然后由于相邻的元素不能相同,那么出现最多的质因数的数量不能超过总数量的一半以上(向上取整),否则肯定会存在两个相邻的元素,此时输出 -1,特判 x == 1 的时候也输出 -1,剩下的情况就需要构造出合法数组,我们可以按元素数量从大到小排序,把数量最多的放在奇数下标上,如1、3、5、7,然后接着放置数量第二多的元素,以此类推。如果奇数位放完了,那么从偶数位开始重复以上过程即可,由于出现最多次数的质因数的数量不超过总数量的一半以上(向上取整),那么肯定不会存在重复的相邻元素,时间复杂度 O(√x + k log k)
代码
cpp
#include<bits/stdc++.h>
using namespace std;
#define int long long // 默认整型用 long long
#define endl '\n'
#define ff first
#define ss second
typedef pair<int, int> pii; // 整数对类型
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int x;
cin >> x;
if (x == 1) // 如果 x = 1,无法分解
{
cout << -1;
return 0;
}
vector<int> cnt; // 存储 x 的质因数
int ma = 0; // 存储某个质因数出现的最大次数
// 分解质因数
for (int i = 2; i * i <= x; i++)
{
int ans = 0;
while (x % i == 0) // 统计 i 出现的次数
{
x /= i;
ans++;
cnt.push_back(i); // 每次出现就加入数组
}
ma = max(ma, ans); // 更新最大次数
}
if (x > 1) // 剩下的 x 是质数
{
cnt.push_back(x);
ma = max(ma, (int)1);
}
// 如果某个质因数次数太多,无法满足要求
if (ma > (cnt.size() + 1) / 2)
{
cout << -1;
}
else
{
priority_queue<pii> q; // 大顶堆,存储{次数, 质因数}
unordered_map<int, int> mp; // 统计每个质因数的次数
for (auto i : cnt)
mp[i]++;
for (auto i : mp)
q.push({i.ss, i.ff}); // 次数大的先出堆
vector<int> a(cnt.size() + 5); // 存放重排后的质因数
int l = 1, r = 2; // 奇数、偶数位置
// 将质因数按次数安排到数组中,使相同质因数不相邻
while (q.size())
{
int u = q.top().ss; // 当前质因数
int ans = q.top().ff; // 当前质因数数量
q.pop();
for (int i = 1; i <= ans; i++)
{
if (l <= cnt.size())
{
a[l] = u;
l += 2; // 先填奇数位置
}
else
{
a[r] = u;
r += 2; // 填偶数位置
}
}
}
cout << cnt.size() << endl; // 输出质因数总个数
for (int i = 1; i <= cnt.size(); i++)
cout << a[i] << ' '; // 输出重排后的质因数
}
}