题目来源
Codeforces Round #696 (Div. 2)
A. Puzzle From the Future
构造题,此题是想要d的值是最大的, 所以我们可以根据b直接构造一个d出来,然后减去b便得到了a。
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= b; --i)
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> IntVec;
const int N = 100000 + 10;
int s[N], t[N];
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--)
{
int n, x;
scanf("%d", &n);
_rep(i, 1, n) {
scanf("%1d", &x);
s[i] = t[i] = x;
}
t[0] = -2;
_rep(i, 1, n) if (t[i] + 1 != t[i - 1]) t[i] += 1;
_rep(i, 1, n) t[i] -= s[i];
_rep(i, 1, n) printf("%d", t[i]);
puts("");
}
return 0;
}
B. Different Divisors
由算术基本定理可以知道一个数是由几个质数的n次方所相乘构成的。题目要求因子是最少四个,那么求最优解就只要四个因子就够了。
那么这个数便是:
x
=
a
1
+
b
1
x = a^1 + b^1
x=a1+b1 (a、b 为质数),四个数分别为 1、a、b、
a
∗
b
a*b
a∗b
题目说两两只差至少大于d,那么意思就是找到一个至少大于
1
+
d
1 + d
1+d的质数a,和找到一个至少大于
a
+
d
a + d
a+d的质数b
a 、b相乘便是结果。
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= b; --i)
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> IntVec;
const int N = 100000 + 10;
int s[N], t[N];
bool is_primes(int n)
{
if (n < 2) return false;
for (int i = 2; i * i <= n; ++i) if (n % i == 0) return false;
return true;
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--)
{
int d;
scanf("%d", &d);
int a = d + 1;
while (!is_primes(a)) a++;
int b = a + d;
while (!is_primes(b)) b++;
printf("%lld\n", a * 1LL * b);
}
return 0;
}
C. Array Destruction
贪心思想,从大到小排序之后,从后面开始依次将数字除去,除不去的即为失败。
数据范围较小,直接暴力即可,暴力可使用一种比较简单的方法,multiset 解决有重复数字出现的情况。
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= b; --i)
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> IntVec;
IntVec alls;
vector<PII> ans;
multiset<int> num;
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--)
{
int n;
scanf("%d", &n);
alls.clear();
_for(i, 0, 2 * n) {
int x;
scanf("%d", &x);
alls.push_back(x);
}
sort(alls.begin(), alls.end());
_for(k, 0, 2 * n - 1)
{
int& first = alls[k];
num.clear();
ans.clear();
_for(i, 0, 2 * n - 1) num.insert(alls[i]);
num.erase(num.find(first));
ans.emplace_back(first, alls.back());
int last = alls.back();
while (!num.empty())
{
int back = *prev(num.end());
num.erase(num.find(back));
auto t = num.find(last - back);
if (t == num.end()) break;
num.erase(t);
ans.emplace_back(last - back, back);
last = back;
}
if (ans.size() == n) break;
}
if (ans.size() == n)
{
puts("YES");
printf("%d\n", ans[0].first + ans[0].second);
for (const auto& p : ans) printf("%d %d\n", p.first, p.second);
}
else puts("NO");
}
return 0;
}
D Cleaning
只能交换一次,从暴力的思想去看的话,就是一个一个的枚举过去,就会有
O
(
n
2
)
O(n^2)
O(n2)的时间复杂度,时间复杂度是有点高的,因为每动一次,就得所有的都枚举一遍,所以要进行优化,每次动的只有相邻两个数,其他元素并没有变化,每次都重复计算了前后的值,遇到这种情况,就得往预处理方向想,把前后的值预处理一下,那么每次交换后就只需要看L[i - 1], a[i + 1], a[i], R[i + 2]
四个值是否符合条件就可以了。
当我们要交换的值在端点或者
n
=
1
n = 1
n=1时,我们是无法判断的,所以要直接处理一下。
#include<bits/stdc++.h>
using namespace std;
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define FOR(i, a, b) for (int i = (a); i >= b; --i)
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> IntVec;
bool success(IntVec a)
{
_for(i, 1, a.size())
{
if (a[i] < a[i - 1]) return false;
a[i] -= a[i - 1];
}
return !a.back();
}
bool slove()
{
int n;
scanf("%d", &n);
IntVec a(n + 1, 0);
_rep(i, 1, n) scanf("%d", &a[i]);
if (n == 1) return false;
if (success(a)) return true;
swap(a[1], a[2]);
if (success(a)) return true;
swap(a[1], a[2]);
swap(a[n], a[n - 1]);
if (success(a)) return true;
swap(a[n], a[n - 1]);
IntVec b(a), L(n + 1, -1), R(n + 1, -1);
_rep(i, 1, n) {
if (b[i] < b[i - 1]) break;
L[i] = b[i] -= b[i - 1];
}
b = a, R[n] = a[n];
FOR(i, n - 1, 1) {
if (b[i] < b[i + 1]) break;
R[i] = b[i] -= b[i + 1];
}
_rep(i, 2, n - 2)
{
IntVec t = { L[i - 1], a[i + 1], a[i], R[i + 2] };
if (L[i - 1] == -1 || R[i + 2] == -1) continue;
if (success(t)) return true;
}
return false;
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--)
{
if (slove()) puts("YES");
else puts("NO");
}
return 0;
}