1001 Yes, Prime Minister
https://acm.hdu.edu.cn/showproblem.php?pid=7025
题意:给出一个数x (−10^7<=xi<=10^7) 让你求出最小的一对(l,r)且(l<=xi<=r) 中为质数。
分析:一个正数x,要么自己为质数,要么x + x + 1或x + x - 1是质数,要么就直接从-x到x,之后再一直找大于x的同性质成立的质数就行了,两个质数之间距离 / 2相差应该不大,直接暴力找就行了。负数-x,直接先加到x变成0,之后往后面找一个为质数或两个相加为质数的情况即可。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e8 + 10;
int n;
bool st[N];
int cnt;
int primes[N];
int t;
void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] <= n / i; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int main()
{
get_primes(N - 1);
scanf("%d", &t);
while (t--) {
int x;
scanf("%d", &x);
if (x == 0) { puts("3"); continue; }
if (x == 1) { puts("2"); continue; }
if (x > 1 && !st[x]) puts("1");
else if (x + x + 1 > 1 && !st[x + x + 1] || x + x - 1 > 1 && !st[x + x - 1]) puts("2");
else {
int pos = lower_bound(primes, primes + cnt, x > 0 ? 2 * abs(x) - 1 : 2 * abs(x) + 3) - primes;
int t2 = 2 * (*lower_bound(primes, primes + cnt, abs(x) + 1));
while (primes[pos] < t2 && ((primes[pos] + 1) & 1)) pos++;
printf("%d\n", min(primes[pos], t2));
}
}
return 0;
}
1004 Decomposition
https://acm.hdu.edu.cn/showproblem.php?pid=7028
题意:给定一个有 n 个顶点的无向完全图(n 是奇数)。需要将其边集划分为 k 个不相交的简单路径,满足第 i 个简单路径的长度为 li (1≤i≤k,1≤li≤n−3),并且每条无向边恰好使用一次。这里长度为 l 的简单路径意味着路径覆盖 l 条边,并且路径中没有重边。
分析:由于要取遍所有的边,且每个点的度为偶数,容易想到用欧拉图来划分。考虑构造一个连接所有点的简单环,则环的边数为n,每条边只用一次,总共能构造个环,则所有的环构成一张欧拉图。构造环时,若起点为x,则依次连接x+1,x-2,x+3···n,x。最后按li切分输出即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
int n, k;
int ans[N];
int main() {
int t;
scanf("%d", &t);
for (int _ = 1, id; _ <= t; _++) {
printf("Case #%d:\n", _);
scanf("%d%d", &n, &k);
id = 0;
ans[id++] = n;
for (int i = n / 2; i; i--) {
int pos = i - 1;
for (int j = 1; j < n; j++) {
ans[id++] = (pos + n - 1) % (n - 1) + 1;
pos += j & 1 ? j : -j;
}
ans[id++] = n;
}
id = 0;
while (k--) {
int l; scanf("%d", &l);
l++;
while (l--) printf("%d%c", ans[id++], " \n"[l == 0]);
id--;
}
}
return 0;
}
1005 Median
https://acm.hdu.edu.cn/showproblem.php?pid=7029
题意:给出n,m,并给出m个bi,需要构造一个数组c,并且分割m个区间后,每个区间的中位数都是bi,且数组c是由1,2 ··· n构成的,且唯一,你需要判断能否构造出这样的数组c。
分析:直接找不为中位数的点,且把每段连续的点都存在不同的vector里,然后判断最长的段的大小和其他的大小进行相比。如果这个最长的段小于其他的段,直接那么就一定存在解,输出yes即可。否则,最后剩下max(块) - sum(其他),然后遍历一遍中位数,记录小于这个块的最小值的中位数的数量cnt,然后比较 cnt 和 上面的剩下的即可。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
assert(m >= 1 && m <= n && n <= 100000);
vector<int> f(n + 2);
f[n + 1] = 1;
while (m--) {
int v;
cin >> v;
f[v] = 1;
}
vector<pair<int, int>> size;
int have = 0;
int count = 0;
for (int i = 1; i <= n + 1; i++) {
if (f[i]) {
if (have) size.push_back(make_pair(have, count));
have = 0;
count += 1;
} else have += 1;
}
sort(size.begin(), size.end());
if (size.empty()) {
cout << "YES\n";
continue;
}
int sum = 0;
for (auto s: size) sum += s.first;
if (size.back().first <= sum - size.back().first + size.back().second) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}