枚举比例倍数生成三个三位数,再检查拼接后的 9 个数字是否恰好是 1 到 9。
OJ: luogu
题目 ID: P1618
难度:入门
标签:枚举字符串python
日期: 2026-07-15 21:30
题意
把数字 1..9 分成三组,组成三个三位数。要求这三个三位数的比例为 A:B:C,按第一个数升序输出所有方案。无解输出 No!!!。
思路
如果三个数比例为 A:B:C,它们一定可以写成:
text
A * times, B * times, C * times因此可以枚举倍数 times。为了让第一个数和第三个数都是三位数,倍数范围可以压缩为:
text
ceil(100 / A) .. floor(999 / C)对每个倍数,拼接三个数的十进制表示。如果拼接后长度为 9,并且数字集合正好是 {1,2,...,9},说明每个数字恰好出现一次且没有 0。
当 A = 0 时,第一个数只能是 0,不可能是三位数,所以直接无解。
Python 知识
f"{x}{y}{z}"可以把三个整数拼接成一个字符串。set(digits) == set("123456789")用集合检查是否只包含1..9。- 同时检查
len(digits) == 9,可以排除重复数字导致集合相同但长度不对的情况。 (100 + a - 1) // a是整数上取整写法。
参考笔记:
/home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md/home/rainboy/mycode/hugo-blog/content/program_language/python/math_tools.md/home/rainboy/mycode/hugo-blog/content/program_language/python/collections_toolkit.md
代码
python
a, b, c = map(int, input().split())
answers = []
if a != 0:
left = (100 + a - 1) // a
right = 999 // c
for times in range(left, right + 1):
x = a * times
y = b * times
z = c * times
digits = f"{x}{y}{z}"
if len(digits) == 9 and set(digits) == set("123456789"):
answers.append((x, y, z))
if answers:
for answer in answers:
print(*answer)
else:
print("No!!!")cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
int a, b, c;
int main() {
cin >> a >> b >> c;
if (a == 0) { cout << "No!!!" << endl; return 0; }
bool found = false;
int left = (100 + a - 1) / a; // 上取整, 保证 x 至少三位数
int right = 999 / c; // 保证 z 最多三位数
for (int t = left; t <= right; t++) {
int x = a * t, y = b * t, z = c * t;
int cnt[10] = {0};
cnt[x/100]++; cnt[x/10%10]++; cnt[x%10]++;
cnt[y/100]++; cnt[y/10%10]++; cnt[y%10]++;
cnt[z/100]++; cnt[z/10%10]++; cnt[z%10]++;
bool ok = true;
for (int d = 1; d <= 9; d++)
if (cnt[d] != 1) { ok = false; break; }
if (!ok || cnt[0] > 0) continue;
found = true;
cout << x << " " << y << " " << z << endl;
}
if (!found) cout << "No!!!" << endl;
return 0;
}复杂度
倍数范围最多几百个,时间复杂度可以看作
总结
这题不要直接枚举所有三位数三元组。抓住比例关系后,只需要枚举一个倍数,再做数字合法性检查。