P1618 三连击(升级版)

题目链接:

#include <bits/stdc++.h>

using namespace std;

int p[10], sum;
int main()
{
	int A, B, C;
	bool flag = false;
	scanf("%d%d%d", &A, &B, &C);
	for (int i = 1; i <= 999 / C; i++) {
		memset(p, 0, sizeof p);
		sum = 0;
		int a = A * i, b = B * i, c = C * i;
		int a1 = a % 10, a2 = (a / 10) % 10, a3 = (a / 100) % 10;
		int b1 = b % 10, b2 = (b / 10) % 10, b3 = (b / 100) % 10;
		int c1 = c % 10, c2 = (c / 10) % 10, c3 = (c / 100) % 10;
		p[a1] = p[a2] = p[a3] = p[b1] = p[b2] = p[b3] = p[c1] = p[c2] = p[c3] = 1;
		for (int i = 1; i <= 9; i++) sum += p[i];
		if (sum == 9) {
			printf("%d %d %d", a, b, c);
			flag = true;
			puts("");
		}
	}
	if (!flag) puts("No!!!");
	return 0;
}

值得一提的是,之所以用 \(A*i、B*i、C*i\) 而不是枚举第一个数 \(x\) 再去计算 \(B / A * x\)\(C / A * x\),是因为若 \(A=0\) 处理起来会比较麻烦,同时 \(B / A\)\(C / A\) 会导致精度不够的问题,因此换乘为除。

需要注意的是,本题一开始还有另外一个 \(AC\) 代码:

#include <cstdio>
#include <set>

int main()
{
	int A, B, C;
	std::set<int> s;
	bool flag = false;
	scanf("%d%d%d", &A, &B, &C);
	for (int i = 1; i <= 999 / C; i++) {
		if (A != 0) {
			s.clear();
			int a = A * i, b = B * i, c = C * i;
			int a1 = a % 10, a2 = (a / 10) % 10, a3 = (a / 100) % 10;
			int b1 = b % 10, b2 = (b / 10) % 10, b3 = (b / 100) % 10;
			int c1 = c % 10, c2 = (c / 10) % 10, c3 = (c / 100) % 10;
			s.insert(a1);
			s.insert(a2);
			s.insert(a3);
			s.insert(b1);
			s.insert(b2);
			s.insert(b3);
			s.insert(c1);
			s.insert(c2);
			s.insert(c3);
			if (s.size() == 9 && a1 + a2 + a3 + b1 + b2 + b3 + c1 + c2 + c3 == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 && a1 * a2 * a3 * b1 * b2 * b3 * c1 * c2 * c3 == 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9) {
				printf("%d %d %d", a, b, c);
				flag = true;
				puts("");
			}
		}
		else {
			puts("No!!!");
			return 0;
		}	
	}
	if (!flag) puts("No!!!");
	return 0;
}

其利用的数学知识为:在集合元素个数相同的情况下,若两个集合中的所有元素之和、之积均相等,则这两个集合相等

但这个原理在某些情况下不满足,比如 \((-4, 0, 4)\)\((-5, 0, 5)\)\((0, 1, 2)\)\((0, 3)\)。所以只当没有办法的时候可以考虑用这个定理来骗分。

posted @ 2024-04-01 08:54  胖柚の工作室  阅读(69)  评论(0)    收藏  举报