【比赛】Codeforces Round #696 (Div. 2)

题目来源

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 ab
题目说两两只差至少大于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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值