Codeforces Round #833 (Div. 2) 题解(A-D)

The Ultimate Square

签到题。答案为(n+1)/2。

#include <bits/stdc++.h>
using namespace std;

void solve() {
	int n;
	cin >> n;
	cout << (n + 1) / 2 << endl;
	return;
}

int main() {
	int n;
	cin >> n;
	while (n--) {
		solve();
	}
	return 0;
}

B Diverse Substrings

我们发现,由于字符串只有0-9十个不同的元素,所以满足题意的字符串最长不会超过100。

所以暴力搜索,时间复杂度为O(100n)。

#include <bits/stdc++.h>
using namespace std;

void solve() {
	int n;
	string a;
	scanf("%d", &n);
	getchar();
	cin >> a;
	int b[10], t, maxm, sum = 0;
	for (int i = 0; i < n; i++) {
		memset(b, 0, sizeof(b));
		t = 0;
		maxm = 0;
		for (int j = 0; j < n - i; j++) {
			if (j == 102)
				break;
			if (b[a[i + j] - '0'] == 0) {
				t++;
			}
			b[a[i + j] - '0']++;
			if (b[a[i + j] - '0'] > maxm)
				maxm = b[a[i + j] - '0'];
			if (t >= maxm)
				sum++;
		}
		//	cout << sum << endl;
	}
	cout << sum << endl;
}

int main() {
	int n;
	cin >> n;
	while (n--) {
		solve();
	}
	return 0;
}

C Zero-Sum Prefixes

这题,首先特别考虑第一个0之前的,前缀和为0符合题意。

然后,第一个0之后,每两个0的区间,取前缀和相同的数量最大的作为答案。

用map存最大值就行。

这题比赛时,忘记在最后加一句result+=maxm,也就是没把最后一个0后面一段考虑上,偏偏样例还是能过的,所以查了二十分钟没发现,实战就没做出来,感觉血亏。

#include <bits/stdc++.h>
using namespace std;
using llong = long long;
void solve() {
	int n, result = 0,maxm = 0;
	cin >> n;
	llong a[n];
	llong sum = 0;
	for (int i = 0; i < n; i++)
		scanf("%lld", &a[i]);
	int j;
	map<llong, int> mp;
	for (j = 0; j < n; j++) {
		if (a[j] == 0)
			break;
		sum += a[j];
		if (sum == 0)
			result++;
	}
	for (; j < n; j++) {
		if (a[j] == 0) {
			result += maxm;
			sum = 0;
			maxm = 0;
			mp.clear();
		}
		sum += a[j];
		mp[sum]++;
		if (mp[sum] > maxm)
			maxm = mp[sum];

	}
	result += maxm;
	cout << result << endl;
	return;
}

int main() {
	int n;
	cin >> n;
	while (n--) {
		solve();
	}
	return 0;
}

D ConstructOR

首先,我们发现只要a或b是奇数,且d是偶数,就无解。因为奇数不可能整除偶数。

然后,我们发现,如果a,b,d无解,那么2a,2b,2d无解。因为这相当于在2进制移了一位,不影响结果。

综上,我们能够推导出,如果min(lsb(a),lsb(b))<lsb(d),就一定无解。其中lsb为二进制下为1的最小位。

因此,如果d的后k位是0,那么a和b的后k位一定是0,否则就无解了。

那如果有解,我们怎么找呢?比较容易的构造是让a|x=b|x=x。

把30位的d后面的k位去掉,我们就得到了一个位数为30-k的奇数d'。

那显然,x的后k位也是0,我们也把后面k位得到x',假设x'的后30-k位都是1,这样的话,就有a|x=b|x=x。

于是x'可以表示为p⋅2^(30−k)+2^(30−k)−1。

接下来要找到p满足整除关系,即(p⋅2^(30−k)+2^(30−k)−1) mod d' == 0。

即(p+1)⋅2^(30−k) mod d' == 1。

即p = (((d'+1)/2)^(30-k) +d'-1) mod d'。

由于d'是奇数,所以显然可以找到一个这样的p符合题意。

#include <bits/stdc++.h>

using namespace std;
using llong = long long;

void solve() {
	llong a, b, d, k = 0, inv, tt = 1;
	cin >> a >> b >> d;
	a = a | b;
	if (a % d == 0) {
		cout << a << endl;
		return;
	}
	while (a % 2 == 0 && d % 2 == 0)
		a /= 2, d /= 2, k++;
	if (a % 2 == 1 && d % 2 == 0) {
		cout << -1 << endl;
		return;
	}
	inv = (d + 1) / 2;
	for (llong i = 0; i < 30 - k; i++)
		tt = tt * inv % d;
	llong res = ((llong)pow(2, 30 - k) * tt - 1) * (llong)pow(2, k);
	cout << res << endl;
}

int main() {
	int t;
	cin >> t;
	while (t--)
		solve();
}

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五百场cf灰名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值