ABC343A-E题解

14 篇文章 0 订阅

A

题目

这里有很多种解法:

第一种

如果 a + b a+b a+b 等于一个常数,那么输出这个常数加上一,否则,输出这个常数

AC Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int a, b;
const int c = 0;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> a >> b;
	if (a + b == c) cout << 1;
	else cout << c;
	return 0;
}

另一种(RP方法)

这种方法如果你的 RP 够好,就会 TLE。
随机一个 0 0 0 9 9 9 的整数,如果这个整数为 a + b a+b a+b,就再次随机一次,否则,就输出这个数。
如果你要 TLE,那么你就要循环至少 5 ⋅ 1 0 8 5\cdot10^8 5108 次,几率为 1 1 0 5 ⋅ 1 0 8 \frac{1}{10^{5\cdot10^8}} 1051081,够你买 114514 114514 114514 次彩票让后次次中头奖了。

AC Code:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int a, b;
int x;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	srand(time(NULL));
	cin >> a >> b;
	while (x == a + b) {
	  x = rand() % 10;
	}
	cout << x;
	return 0;
}

B

题目

这个简单,如果 a i j a_{ij} aij 1 1 1 时输出 j j j 就行了。

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int n;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			int x;
			cin >> x;
			if (x) cout << j << ' ';
		}
		cout << '\n';
	}
	return 0;
}

C

题目

无脑写法,设答案为 x 3 x^3 x3,如果枚举 x 3 x^3 x3 会超时,那么枚举 x x x 就不会了,可能的 x x x 最多有 1 0 6 10^6 106 个。

然后取走 x x x 的每一位写法:先拷贝一份 x x x,每次用 x m o d    10 x\mod10 xmod10 取走 x x x 的个位,再将 x x x 减去 x m o d    10 x\mod10 xmod10 x x x 再除以 10 10 10,虽然 c++ 自动向下取整,这样做是为了方便判断退出条件: x = 0 x=0 x=0

把取出来的每一位的数放在数组里,再用一个数组反着存每一位,如果两个数组相等,说明 x x x 回文。

暴力,判断,就完结撒花了。

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
long long n;
long long ans;
bool check(long long x) {
	vector<int> a, b;
	long long tmp = x;
	while (tmp > 0) {
		a.push_back(tmp % 10);
		tmp -= tmp % 10;
		tmp /= 10;
	}
	for (int i = 0; i < (int)a.size(); i++) {
		b.push_back(a[(int)a.size() - i - 1]);
	}
	for (int i = 0; i < (int)a.size(); i++) {
		if (a[i] != b[i]) return 0;
	}
	return 1;
}
int main() {
	cin >> n;
	for (long long i = 1; i * i * i <= n; i++) {
		if (check(i * i * i)) ans = i * i * i;
	}
	cout << ans;
	return 0;
}

D

题目

我们发现,设某个人的分数为 x x x,当 x x x 的值有变化时,分数为 x x x 的个数才有变化。
我们存下每一个人的分数,再用一个 map 数组存储每一个分数的个数,一开始分数为 0 0 0 的人数为 n n n,然后当一个人的分数发生改变时,设这个人之前的分数为 p 1 p1 p1,改变后的分数为 p 2 p2 p2,如果改变后分数为 p 1 p1 p1 的个数变为了 0 0 0,说明少了一种分数,分数种类数减少一,如果改变后 p 2 p2 p2 的个数变成了一,说明多了一种分数,分数种类数加一。

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
long long n, t;
struct node{
	long long a, b;
};
node a[200100];
long long pts[200100];
bool cmp(node a, node b) {
	return a.a < b.a;
}
map<long long, long long> cnt;
long long cntt = 1;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> t;
	for (long long i = 1; i <= t; i++) cin >> a[i].a >> a[i].b;
	cnt[0] = n;
	for (long long i = 1; i <= t; i++) {
		cnt[pts[a[i].a]]--;
		if (cnt[pts[a[i].a]] == 0) cntt--;
		pts[a[i].a] += a[i].b;
		cnt[pts[a[i].a]]++;
		if (cnt[pts[a[i].a]] == 1) cntt++;
		cout << cntt << '\n';
	}
	return 0;
}

E

题目

这里强调的是相对位置,所以第一个立方体直接放在 ( 0 , 0 , 0 ) (0,0,0) (0,0,0) 是绝对没有问题的。然后如果有两个立方体并不相交,那么两个立方体的相对位置对答案没有影响。因为两个立方体无论怎么放置,它们之间相交的部分都是 0 0 0,不会给 V 1 , V 2 , V 3 V_1,V_2,V_3 V1,V2,V3 加上某一个值。
所以三个立方体都不相交就是 − 7 ≤ x ≤ 14 -7\le x \le 14 7x14 − 7 ≤ y ≤ 14 -7 \le y \le 14 7y14 − 7 ≤ z ≤ 14 -7 \le z \le 14 7z14 的情况。

所以对于剩下两个立方体的坐标,从 − 7 -7 7 枚举到 14 14 14 即可。

问题来了,怎么算答案?

我们先来解决一个好解决一点的问题,算两个立方体 ( a 1 , b 1 , c 1 ) (a_1,b_1,c_1) (a1,b1,c1) ( a 2 , b 2 , c 2 ) (a_2,b_2,c_2) (a2,b2,c2) 的体积。

它们的公共部分表示为:

max ⁡ ( a 1 , a 2 ) ≤ x ≤ min ⁡ ( a 1 + 7 , a 2 + 7 ) \max(a_1,a_2) \le x \le \min(a_1+7,a_2+7) max(a1,a2)xmin(a1+7,a2+7)

max ⁡ ( b 1 , b 2 ) ≤ x ≤ min ⁡ ( b 1 + 7 , b 2 + 7 ) \max(b_1,b_2) \le x \le \min(b_1+7,b_2+7) max(b1,b2)xmin(b1+7,b2+7)

max ⁡ ( c 1 , c 2 ) ≤ x ≤ min ⁡ ( c 1 + 7 , c 2 + 7 ) \max(c_1,c_2) \le x \le \min(c_1+7,c_2+7) max(c1,c2)xmin(c1+7,c2+7)

所以算这两个立方体的体积就可以用公共部分的表达方式来算:

( min ⁡ ( a 1 , a 2 ) + 7 − max ⁡ ( a 1 , a 2 ) ) ⋅ ( min ⁡ ( b 1 , b 2 ) + 7 − max ⁡ ( b 1 , b 2 ) ) ⋅ ( min ⁡ ( c 1 , c 2 ) + 7 − max ⁡ ( a 1 , a 2 ) ) (\min(a_1,a_2)+7-\max(a_1,a_2))\cdot(\min(b_1,b_2)+7-\max(b_1,b_2))\cdot(\min(c_1,c_2)+7-\max(a_1,a_2)) (min(a1,a2)+7max(a1,a2))(min(b1,b2)+7max(b1,b2))(min(c1,c2)+7max(a1,a2))

算三个立方体 ( a 1 , b 1 , c 1 ) (a_1,b_1,c_1) (a1,b1,c1) ( a 2 , b 2 , c 2 ) (a_2,b_2,c_2) (a2,b2,c2) ( a 3 , b 3 , c 3 ) (a_3,b_3,c_3) (a3,b3,c3) 的体积就是上面的问题多一个 ( a 3 , b 3 , c 3 ) (a_3,b_3,c_3) (a3,b3,c3) 而已。

于是乎,答案就出来了:

V 3 = C 1 ∩ C 2 ∩ C 3 V_3=C_1 \cap C_2 \cap C_3 V3=C1C2C3

V 2 = C 1 ∩ C 2 + C 2 ∩ C 3 + C 1 ∩ C 3 − 3 V 3 V_2=C_1 \cap C_2 + C_2 \cap C_3 +C_1 \cap C_3 - 3V_3 V2=C1C2+C2C3+C1C33V3

V 1 = 3 × 7 3 − 2 V 2 − 3 V 3 V_1=3\times7^3-2V_2-3V_3 V1=3×732V23V3

乘二、三是因为要给每一个立方体都减去一个。

所以,出来吧,AC Code!

AC Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int v1, v2, v3, v11, v22, v33;
int f(int a1, int b1, int c1, int a2, int b2, int c2) {
	int res = 1;
	res *= max(0, min(a1, a2) + 7 - max(a1, a2));
	res *= max(0, min(b1, b2) + 7 - max(b1, b2));
	res *= max(0, min(c1, c2) + 7 - max(c1, c2));
	return res;
}
int f(int a1, int b1, int c1, int a2, int b2, int c2, int a3, int b3, int c3) {
	int res = 1;
	res *= max(0, min({a1, a2, a3}) + 7 - max({a1, a2, a3}));
	res *= max(0, min({b1, b2, b3}) + 7 - max({b1, b2, b3}));
	res *= max(0, min({c1, c2, c3}) + 7 - max({c1, c2, c3}));
	return res;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> v1 >> v2 >> v3;
	for (int a2 = -7; a2 <= 14; a2++) {
		for (int b2 = -7; b2 <= 14; b2++) {
			for (int c2 = -7; c2 <= 14; c2++) {
				for (int a3 = -7; a3 <= 14; a3++) {
					for (int b3 = -7; b3 <= 14; b3++) {
						for (int c3 = -7; c3 <= 14; c3++) {
							v33 = f(0, 0, 0, a2, b2, c2, a3, b3, c3);
							v22 = f(0, 0, 0, a2, b2, c2) + f(0, 0, 0, a3, b3, c3) + f(a2, b2, c2, a3, b3, c3) -
							v33 * 3;
							v11 = 3 * 7 * 7 * 7 - v22 * 2 - v33 * 3;
							if (v1 != v11 or v2 != v22 or v3 != v33) continue;
							printf("Yes\n0 0 0 %d %d %d %d %d %d\n", a2, b2, c2, a3, b3, c3);
							return 0;
						}
					}
				}
			}
		}
	}
	cout << "No\n";
	return 0;
}
  • 30
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值