用1,2,3……,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出所有解。
#include<time.h>
int main()
{
int a,b,c,d,e,f,g,h,i;
for(a=1;a<10;a++)
for(b=1;b<10;b++)
for(c=1;c<10;c++)
for(d=1;d<10;d++)
for(e=1;e<10;e++)
for(f=1;f<10;f++)
for(g=1;g<10;g++)
for(h=1;h<10;h++)
for(i=1;i<10;i++)
{
if(a==b||a==c||a==d||a==e||a==f||a==g||a==h||a==i||b==c||b==d||b==e||b==f||b==g||b==h||b==i||c==d||c==e||c==f||c==g||c==h||c==i||d==e||d==f||d==g||d==h||d==i||e==f||e==g||e==h||e==i||f==g||f==h||f==i||g==h||g==i||h==i)
break;
else if((a*100+b*10+c)*2==d*100+e*10+f&&(a*100+b*10+c)*3==g*100+h*10+i)
printf("%d %d %d\n",a*100+b*10+c,d*100+e*10+f,g*100+h*10+i);
else break;
}
printf("Time used=%.21f\n",(double)clock()/CLOCKS_PER_SEC);
return 0;
}
这个是我能想到的程序,但是
理论答案输出:
273 546 819
327 654 981
219 438 657
192 384 576
实际输出:
327 654 981
求大神指教哪里出问题了,还有就是简单方法怎么做,希望步骤能多些注释,谢谢!!
这个是我能想到的程序,但是 展开
这道题以前做过, 有点印象
其实这道题就2个地方要注意, 也是解题关键
abc:def:ghi=1:2:3
1,2,3……,9组成3个三位数abc,def和ghi,每个数字恰好使用一次
对于第一个地方, 我们可以用1个循环, 加3个变量来实现
就是
for(i = 123; i <= 329; i++)
{
j = i * 2; //i的2倍
k = i * 3; //i的3倍
}
i 最小只能是123, 最大只能是329(因为最大数字只能是987)
第2个地方的实现, 我们可以用数学的方法来实现
1~9加起来真能是45, 1~9乘起来只能是362880
所以我们可以将前面的i, j, k分别分解出来的9位数字相加, 相乘,
看最后的结果是不是45,362880
具体代码
//用1,2,3……,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出所有解。
#include <stdio.h>
void result(int num, int &result_add, int &result_mul)
{
int i, j, k;
i = num / 100; //百位
j = num / 10 % 10; //十位
k = num % 10; //个位
result_add += i + j + k; //分解出来的位数相加
result_mul *= i * j * k; //相乘
}
int main()
{
int i, j, k;
int result_add, result_mul;
for(i = 123; i <=329; i++)
{
j = i * 2;
k = i * 3;
result_add = 0;
result_mul = 1;
result(i, result_add, result_mul);
result(j, result_add, result_mul);
result(k, result_add, result_mul);
if(result_add == 45 && result_mul == 362880)
printf("%d %d %d\n", i, j, k);
}
return 0;
}
效果:
PS:若有不明白的地方, 请追问
大神可以帮我看下我的程序哪里出错了吗,谢谢!
问题出在 break;上
以下是可行的实现:
//忽略头
int a,b,c,d,e,f,g,h,i;
for(a=1;a<10;a++)
for(b=1;b<10;b++)
for(c=1;c<10;c++)
for(d=1;d<10;d++)
for(e=1;e<10;e++)
for(f=1;f<10;f++)
for(g=1;g<10;g++)
for(h=1;h<10;h++)
for(i=1;i<10;i++)
{
if(a==b||a==c||a==d||a==e||a==f||a==g||a==h||a==i
||b==c||b==d||b==e||b==f||b==g||b==h||b==i
||c==d||c==e||c==f||c==g||c==h||c==i||d==e
||d==f||d==g||d==h||d==i||e==f||e==g||e==h
||e==i||f==g||f==h||f==i||g==h||g==i||h==i)
continue;
else{
if((a*100+b*10+c)*2==d*100+e*10+f&&(a*100+b*10+c)*3==g*100+h*10+i)
printf("%d %d %d\n",a*100+b*10+c,d*100+e*10+f,g*100+h*10+i);
else
continue;
}
}
printf("Time used=%.21f\n",(double)clock()/CLOCKS_PER_SEC);
return 0;
以下是更好的实现:主要是利用一个数组实现集合(set)的功能。
//忽略头
for(int i = 102;i<333;i++){
int a[3];
a[0] = i;
a[1] = 2*i;
a[2] = 3*i;
int hole[10];
for(int j = 0;j<10;j++)
hole[j]=0;
int flag = 1;
for(int index = 0;index<3 && flag==1 ;index++){
if(hole[a[index]%10]==0)
hole[a[index]%10]=1;
else
flag=0;
if(hole[a[index]/10 %10]==0)
hole[a[index]/10 %10]=1;
else
flag=0;
if(hole[a[index]/100]==0)
hole[a[index]/100]=1;
else
flag=0;
}
if(flag==1)
printf("%d %d %d\n",i,2*i,3*i);
}
return 0;
目前的最佳答案是一个不错的方法,数学支持如下:
1~9加起来真能是45, 1~9乘起来只能是362880
其实应该反过来说
若9个小于10 的正整数的和为45,积为362880,则这9个数是1,2,3...9的一个排列。
调整法可证。
利用遍历,因为组成的数的最小值为123,最大值为789,同时,三个数满足1:2:3的比例关系,因此只需要遍历abc从最小值到最大值即可。
abc最小值为123,因为abc:ghi=1:3,所以abc的最大值为组成三位数的最大值的三分之一,即329。此时只需要遍历abc从123到329即可。
def=abc*2,ghi=abc*3。
这里你需要知道1-9这9个数的和为45,乘积为362880,只需要判断生成的数每一位满足这个条件即可。
具体程序如下(C++):
#include <bits/stdc++.h>
using namespace std;
int sum(int i) //求三位数每位相加之和
{
return (int)(i / 100) + (int)(i / 10 % 10) + (int)(i % 10);
}
int mult(int i) //求三位数每位相乘之积
{
return (int)(i / 100) * (int)(i / 10 % 10) * (int)(i % 10);
}
int main()
{
//对于1,2,...,9这些书来说,最小的数为123,最大的数为987,因为abc:def:ghi=1:2:3,所以abc的最大值是所组成的最大数的三分之一,即329.
for (int i = 123; i < 987 / 3; i++)
{
int j = i * 2;
int k = i * 3;
if (j <= 987 && k <=987)
{
//1+2+3+...+9=45,1*2*3*...*9=362880,因此只要判断这三个数每一位相加等于45,相乘等于362880即可。
if(sum(i)+sum(j)+sum(k)==45 && mult(i)*mult(j)*mult(k)==362880)
cout << "i=" << i << "; j=" << j << ";k=" << k << endl;
}
}
system("pause");
return 0;
}
void main()
{
int x,y,z;
int str[10];
int s,j=0;//用于冒泡法排序
int a,b,c,d,e,f,g,h,i;
int count,num=0,o=0;//用于计数
x=122;
L1:x++;
y=2*x;z=3*x;
a=x/100;b=(x/10)%10;c=x%10; //把三位数的每一位数字截下来,a,b,c分别为百,十,个位
d=y/100;e=(y/10)%10;f=y%10;
g=z/100;h=(z/10)%10;i=z%10;
str[0]=a;str[1]=b;str[2]=c;str[3]=d;str[4]=e;str[5]=f;str[6]=g;str[7]=h;str[8]=i;
count=9;
for(s=0;s<9;s++)
{
for(j=1;j<9;j++)
{
if(s!=j){
if(str[s]==str[j]||str[s]==0)
{
goto L1;
}
}
}
}
int Num=100*str[6]+10*str[7]+str[8];
int sum=a+b+c+d+e+f+g+h+i;
for(i=0;i<9;i++)
{
if(sum==45){
if(Num<=987)
{
cout<<str[i];
}
if((i+1)%3==0)
{
cout<<" ";
}
}
}
cout<<endl;
if(Num<987){
goto L1;
}
int func(int a)
{
int temp, flag[10] = {1};
for(temp=a%10;a;a/=10,temp=a%10)
if(flag[temp]++ == 1) return 0;
return 1;
}
void main()
{
int base;
for(base=123; base<345; base++)
if(func(base*1000000+base*2*1000+base*3)==1)
printf("%d %d %d\n", base, base*2, base*3);
}