A茕茕孑立之影
题目理解是找一个质数与数组里面所有的数都互质,那我们找一个极大的质数就行了。 判断一下存不存在 1 ,如果不存在就输出 1e7 就行了。
注意一下 1e7 是double 型的,输出的时候要输出 int 型的,转化一下或者直接输出就行
int n; cin >> n;
vector<int> a(n);
for (int i= 0; i < n; i ++) cin >> a[i];
sort(a.begin(), a.end());
if (a[0] == 1) cout << -1 << "\n";
else cout << 10000007 << "\n";
B 一气贯通之刃
首先明确一下简单路径是什么
简单路径是指没有重边和闭环的图, 顶点不重复。那我们通过录入一下无向图。然后判断一下每个点的度数就可以了。
如果度数 > 2 那么一定是会重复经历的,就不是简单路径。
如果度数 == 1 说明只有出度,没有入度,或者只有入度,没有出度,那只需要记录一下即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100010;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n; cin >> n;
vector<vector<int>> g(n + 1);
for (int i = 0; i < n - 1; i ++)
{
int u, v; cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
bool flag = false;
int ans1 = 0, ans2 = 0;
for (int i = 1; i <= n; i ++)
{
if (g[i].size() > 2) flag = true;
if (g[i].size() == 1)
{
if (!ans1) ans1 = i;
else if (!ans2) ans2 = i;
}
}
if (flag)
cout << -1;
else
cout << ans1 << " " << ans2;
return 0;
}
D 双生双宿之决
排序然后暴力就行
要判断一下前后两个相同的数字相同不相同就行了
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N = 1e6 + 10;
int a[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t; cin >> t;
while (t --)
{
int n; cin >> n;
int sum = 0;
for (int i = 1; i <= n; i ++)
{
cin >> a[i];
sum += a[i];
}
if (n & 1)
{
cout << "No" << "\n";
continue;
}
sort(a + 1, a + 1 + n);
bool flag1 = true, flag2 = true;
for (int i = 1; i <= n / 2; i ++)
{
if (a[i] != a[1])
flag1 = false;
}
for (int i = n / 2 + 1; i <= n; i ++)
{
if (a[n] != a[i])
flag2 = false;
}
if (flag1 && flag2 && a[1] != a[n]) cout << "Yes" << "\n";
else cout << "No" << "\n";
}
return 0;
}
E 双生双宿之错
中位数定理:所有数到中位数的距离和是最近的。
通过上面这个定理,我们可以容易的出来左侧右侧最近的答案。由于左右两个数不能一样,所以我们判断一下让两个数不一样就行了。
代码如下:
#include <bits/stdc++.h>
#define int long long
void solve()
{
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++)
std::cin >> a[i];
std::sort(a.begin(), a.end());
int half = n / 2;
int lh = a[half / 2], rh = a[half + half / 2];
int ans = 1e18;
int res;
for (int i = lh - 1; i <= lh + 1; i++)
for (int j = rh - 1; j <= rh + 1; j++)
{
if (i == j)
continue;
res = 0;
for (int k = 0; k < half; k++)
res += abs(a[k] - i);
for (int k = n / 2; k < n; k++)
res += abs(a[k] - j);
ans = std::min(ans, res);
}
std::cout << ans << "\n";
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int _;
std::cin >> _;
while (_--)
{
solve();
}
return 0;
}
G井然有序之衡
排序之后进行相减统计需要加的数量和减的数量,最后输出即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N = 1e6 + 10;
int a[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n; cin >> n;
for (int i = 1; i <= n; i ++)
{
cin >> a[i];
}
sort(a + 1, a + 1 + n);
int jia = 0, jian = 0;
for (int i = 1; i <= n; i ++)
{
i - a[i] > 0 ? jia += i - a[i] : jian += i - a[i];
}
if (jia + jian == 0)
{
cout << jia;
}
else cout << -1;
return 0;
}
H 井然有序之窗
要在范围里面,考虑贪心。先对左边界进行排序然后进行遍历,比如说第一个样例, 1 3 肯定是对应的 1 是最好的,剩下的 1 4 和 2 3 那就相当于是 2 4, 2 3 那这时候要建一个堆来进行排序,对右边界小的先进行 pop,然后记录一下。
做这种题要考虑贪心,是对左边界进行贪心还是有边界进行贪心,还是有其他的什么操作。
综上,比如说现在遍历到了 1 ,我们可以把左边界全为 1 的放到小根堆里面,然后进行 pop。
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int, int> PII;
constexpr int N = 1e6 + 10;
struct node
{
int l, r, pos;
int eend;
} a[N];
priority_queue<PII, vector<PII>,greater<PII>> q;
bool cmp(node a, node b)
{
if (a.l != b.l)
return a.l < b.l;
return a.r < b.r;
}
struct node1
{
int quj, id;
} ans[N];
bool cmp1(node1 a, node1 b)
{
return a.quj < b.quj;
}
bool st[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n; cin >> n;
for (int i = 1; i <= n; i ++)
{
cin >> a[i].l >> a[i].r;
a[i].pos = i;
}
sort(a + 1, a + 1 + n, cmp);
int j = 1;
for (int i = 1; i <= n; i ++)
{
for (; j <= n;)
{
if (a[j].l == i)
{
q.push({a[j].r, a[j].pos});
j ++;
}
else
break;
}
if (q.empty())
{
cout << -1;
return 0;
}
auto x = q.top();
if (x.first < i || q.empty()) // 如果队列里面就没有包含 i 的并且堆里面是空的,就直接 -1
{
cout << -1;
return 0;
}
q.pop();
ans[i].id = i; ans[i].quj = x.second;
}
sort(ans + 1, ans + 1 + n, cmp1);
for (int i = 1; i <= n; i ++)
cout << ans[i].id << " ";
return 0;
}
硝基甲苯之袭
硝基甲苯之袭
这个题要知道异或的一个规律
** 由 a ^ b = c, 可知 a ^ c = b, b ^ c = a **
那么我们可以把原来的式子写成 ai ^ g == aj
设 g = gcd(ai, aj). 我们知道 g 一定是 ai 的因数,那么我们枚举 ai 的因数即可。出现结果之后让之前的元素和这个元素相乘即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N = 1e6 + 10;
int cnt[N];
int a[N];
int gcd(int a, int b) {return b ? gcd(b, a % b) : a;};
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n; cin >> n;
int ans = 0;
for (int i = 1; i <= n; i ++)
{
int x; cin >> x;
a[i] = x;
cnt[x] ++; // 记录下 x 的个数
}
for (int i = 1; i <= n; i ++)
for (int x = 1; x * x <= a[i]; x ++) // 寻找 a[i] 的因数
{
if (a[i] % x == 0)
{
if (gcd(a[i], a[i] ^ x) == x) ans += cnt[a[i] ^ x];
if (x * x != a[i] && gcd((a[i] / x) ^ a[i], a[i] / x) == a[i] / x) ans += cnt[a[i] / x ^ a[i]]; 有两种情况,一起加上即可。
}
}
cout << ans / 2; // 最后的答案会是原来的两倍,要除以 2
return 0;
}
M 数值膨胀之美
最小化数组的极差,那么首先想到的是最小值变成原来的 2 倍,那么这样就i会有问题。如果最小值变为原来的 2 倍,比次小值大了怎么办。所以这时候次小值也要变为原来的 2 倍。
那么我们要考虑区间的最小值。是一个经典的 RMQ 问题,我们可以用 ST 表来实现这个
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
#define int long long
const int N = 1e5 + 10;
const int logN = 20;
int fa[N][logN + 1], fm[N][logN + 1];
int Logn[N];
PII a[N];
// 初始化Logn数组
void init()
{
Logn[1] = 0;
for (int i = 2; i < N; i++)
Logn[i] = Logn[i / 2] + 1;
}
// 获取区间最大值
int getmax(int l, int r)
{
int s = Logn[r - l + 1];
return max(fa[l][s], fa[r - (1 << s) + 1][s]);
}
// 获取区间最小值
int getmin(int l, int r)
{
int s = Logn[r - l + 1];
return min(fm[l][s], fm[r - (1 << s) + 1][s]);
}
signed main()
{
init();
int n;
cin >> n;
// 输入处理并初始化fa和fm数组以及a数组
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
fa[i][0] = x; // 初始时,每个点的最大值就是它本身
fm[i][0] = x; // 同样,初始时,每个点的最小值也是它本身
a[i] = {x, i}; // 记录原数组元素及其索
}
// 对a数组按元素值进行排序
sort(a + 1, a + 1 + n);
// 构建ST表
for (int j = 1; j <= logN; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
fa[i][j] = max(fa[i][j - 1], fa[i + (1 << (j - 1))][j - 1]); // 更新最大值ST表
fm[i][j] = min(fm[i][j - 1], fm[i + (1 << (j - 1))][j - 1]); // 更新最小值ST表
}
int l = 1e9, r = 0;
int ans = 1e9;
for (int i = 1; i <= n; i++)
{
int u = a[i].second;
l = min(u, l), r = max(r, u);
int mmax = getmax(l, r) * 2;
int mmin = getmin(l, r) * 2;
int mmax1 = -1e9, mmax2 = -1e9, mmin1 = 1e9, mmin2 = 1e9;
if (l > 1)
{
int l1 = 1, r1 = l - 1;
mmax = max(mmax, getmax(l1, r1));
mmin = min(mmin, getmin(l1, r1));
}
if (r < n)
{
int l2 = r + 1, r2 = n;
mmax = max(mmax, getmax(l2, r2));
mmin = min(getmin(l2, r2), mmin);
}
// cout << ans << "\n";
ans = min((mmax - mmin), ans);
}
cout << ans;
return 0;
}

被折叠的 条评论
为什么被折叠?



