三连击(升级版)
题目描述
将 $1, 2,\ldots, 9$ 共 $9$ 个数分成三组,分别组成三个三位数,且使这三个三位数的比例是 $A:B:C$,试求出所有满足条件的三个三位数,若无解,输出 No!!!
。
//感谢黄小U饮品完善题意
输入格式
三个数,$A,B,C$。
输出格式
若干行,每行 $3$ 个数字。按照每行第一个数字升序排列。
样例 #1
样例输入 #1
1 2 3
样例输出 #1
192 384 576
219 438 657
273 546 819
327 654 981
提示
保证 $A<B<C$。
$\text{upd 2022.8.3}$:新增加二组 Hack 数据。
题解
这题审题太容易出错了 我以为是一个三位数 1~9不能重复 结果是三个三位数 所有位上的数字都不能重复
这题掌握的一个新知识 segmentation fault
有可能是scanf里面忘加&号了
#include <bits/stdc++.h>
using namespace std;
int a[11], b1, b2, b3, k1, k2, k3, l, ans;
int main()
{
scanf("%d%d%d", &k1, &k2, &k3);
for (int i = 1; i <= 1000 / k3; i ++ ) //这里i<=1000/k3 是因为最大倍数是k3 所以在三位数内我们能取的最大数值就是1000/k3
{
b1 = i * k1;
b2 = i * k2;
b3 = i * k3;
if (b2 > 999 || b3 > 999) break;
//分别记录一下每个三位数每一位数字的使用情况
for (int j = 1; j <= 3; j ++ )
{
a[b1 % 10] ++ ;
b1 /= 10;
}
for (int j = 1; j <= 3; j ++ )
{
a[b2 % 10] ++ ;
b2 /= 10;
}
for (int j = 1; j <= 3; j ++ )
{
a[b3 % 10] ++ ;
b3 /= 10;
}
//判断每个数字有没有过多使用 如果过多使用 标记一下防止后面输出了 并退出循环
for (int j = 1; j <= 9; j ++ )
{
if (a[j] != 1)
{
l = 1;
break;
}
}
//对a数组清零方便下次循环使用
for (int j = 1; j <= 9; j ++ ) a[j] = 0;
if (!l) //如果该循环内没有被标记 输出三个数组
{
printf("%d %d %d\n", i * k1, i * k2, i * k3); //注意b1 b2 b3已经被改变了 这里要重新输入三个三位数
ans ++ ; //记录方案数 方便无解的时候输出no
}
else l = 0; //标记清空
}
if (!ans) puts("No!!!"); //无解的情况
return 0;
}
法二
利用stl库内的next_permutation
函数实现
题目有A B C 三个比例关系
那么我们可以利用1~9内的数字 将所有三位数全排列 找到其中符合题目要求的点 输出
通过b3[9] 1~9数字排列 这样的全排列 我们就可以满足题目要求的 所有的三位数位上数字都不重复
妙!
#include <bits/stdc++.h>
using namespace std;
int b3[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; //将所有可能用到的数字罗列出来
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
int ans = 0;
do{
int a1 = 100 * b3[0] + 10 * b3[1] + b3[2];
int b1 = 100 * b3[3] + 10 * b3[4] + b3[5];
int c1 = 100 * b3[6] + 10 * b3[7] + b3[8];
if ((a1 * b == b1 && a1 * c == c1) || (a1 == a && b1 == b && c1 == c))
{
ans ++ ;
printf("%d %d %d\n", a1, b1, c1);
}
}while (next_permutation(b3, b3 + 9));
if (!ans) puts("No!!!");
return 0;
}