2024“钉耙编程”中国大学生算法设计超级联赛(8)

传送门

1007 cats 的 k-xor

由于是不进位相加,所以一定满足 a + b \ge c。因此有

  1. a + b < c 时,没有进制满足要求。
  2. a + b = c 时,说明原本的加法就不需要进位,有无限个 k 满足要求。
  3. a + b > c 时,这是由于加法没有进位导致的,而且 k 一定是 a + b - c 的因数。枚举 a + b - c的因数,判断该因数是否为满足条件的进制。
#include <bits/stdc++.h>
using namespace std;

#define int long long

int t;

inline int read() {
	int x = 0, f = 1; char c = getchar();
	while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}

bool check(int a, int b, int c, int k) {
	while (a || b || c) {
		int aa = a % k, bb = b % k, cc = c % k;
		if ((aa + bb) % k != cc) return false;
		a /= k, b /= k, c /= k;
	}
	return true;
}

signed main() {
	t = read();
	int a, b, c;
	while (t--) {
		int ans = 0LL;
		a = read(), b = read(), c = read();
		if (a + b == c) { puts("-1"); continue; }
		if (a + b < c) { puts("0"); continue; }
		int tar = a + b - c;
		for (int i = 1; i * i <= tar; i++) {
			if (tar % i == 0) {
				if (i >= 2 && check(a, b, c, i)) ans++;
				if (i * i < tar && tar / i >= 2 && check(a, b, c, tar / i)) ans++;
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

1012 cats 的电脑中毒

对于任意字符串 S_1, S_2, S_3,记录任意两个串之间对应位不同的位数,记最大的数为 num,答案为 n - \frac{num + 1}{2}

证明:

  • 由于字符串的顺序不影响结果,假设 S_1 与 S_2 相差的位数最多,总共 num 位不同,n - num 位相同,那么在只考虑这两个字符串的情况下总共需要 n - \frac{num + 1}{2} 步。
  1. 此时最难变成的字符串 tar 为,当 S_{1_i} = S_{2_i} 的时候,该字符串对应位置上字符与这两个字符串对应字符不同;剩余位置上的字符,当 num 为偶数时,一半跟字符串 S_1 对应位置字符相同,另一半与 S_2 对应位置上的字符相同;当 num 为奇数时,\frac{num + 1}{2} 位跟 S_1 对应位置字符相同, \frac{num}{2} 位跟 S_2 对应位置上的字符相同(反过来也一样)。
  2. 由于 S_1 与 S_2 跟 tar 最多有 \frac{num + 1}{2} 位相同,所以需要 n - \frac{num + 1}{2} 步(num为偶数时,加一后除 2 结果不受影响)
  • 由于字符串的顺序不影响结果,假设 S_1 与字符串 tar 相差位数最少,总共相差 n - \frac{num + 1}{2} 位。
  • 此时再考虑字符串 S_3,结果一定不会比 n - \frac{num + 1}{2} 更劣。假设 S_1 与 S_3 字符串有 cnt 位不同,那么一定有 cnt \le num。同理,再只考虑 S_1 与 S_3 的情况下, S_1 与 S_3 总共需要 n - \frac{cnt + 1}{2} \ge n - \frac{num + 1}{2} 步。(只考虑 S_2 与 S_3 同理)。
  • 从 S_3 变成字符串 tar 步骤一定多与由 S_1 变得(通过样例观察得出,不太会证明)。

由此,可以得出 ans = n - \frac{num + 1}{ 2}

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

int dif(string x, string y) {
	int num = 0;
	for (int i = 0; i < x.size(); i++) {
		if (x[i] != y[i]) num++;
	}
	return num;
}

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t, n;
	string a, b, c;
	cin >> t;
	while (t--) {
		cin >> n;
		cin >> a >> b >> c;
		int num = dif(a, b);
		num = max(num, dif(b, c));
		num = max(num, dif(a, c));
		cout << n - (num + 1) / 2 << '\n';
	}
	return 0;
}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值