作者utomaya (乌托马雅)
看板puzzle
标题Re: [问题] 填数字(小町蛀虫算 009)
时间Wed Jul 8 13:45:13 2009
※ 引述《fredgo (F.D.)》之铭言:
: ※ 引述《utomaya (乌托马雅)》之铭言:
: : □ □ □
: : ________ - ________ + ________ = 0
: : □ □ □ □ □ □
: 1/26 - 4/39 + 5/78 = 0
: 1/32 - 5/48 + 7/96 = 0
: 1/96 - 5/32 + 7/48 = 0
: 5/78 - 4/39 + 1/26 = 0
: 7/48 - 5/32 + 1/96 = 0
: 7/96 - 5/48 + 1/32 = 0
: : □ □ □ □
: : ________ - ________ + _________ = 0
: : □ □ □ □ □
: 1/4 - 29/76 + 5/38 = 0
: 3/4 - 59/68 + 2/17 = 0
: : 上列两式中,请在□中填入1~9的数字,使算式成立
: : 每个式子中1~9数字只能用一次。且每个分数必须为最简分数,不可再约分。
: : 且不能为假分数
: : 例如
: : 7 3 4
: : ________ - ________ + _________ = 0 虽然1~9只用一次,且算式成立
: : 98 21 56
: : 但不是最简分数,故为不合法的答案。
: : 5 29 7
: : ________ - ________ + _________ = 0 有假分数,也是不合法的答案。
: : 3 16 48
: 找到这几组解
: 也许设计有唯一解的题目
: 会比较好推理吧^^a
是真的推理吗? 还是跑程式的?
我是故意设计出那麽多解的,因为才可以看出是跑程式解出的,还是靠推理解出的?
怎麽你的解答和我的程式跑出来的解答一样
连顺序都一模一样?
如果是推理的,大概找到一组解,就会认为自己已经解答出来了
(事实上,如果是用推理的,要找到一组解也很不简单)
只有跑程式才能把所有的解找出来
在这边说个故事好了,
□ □ □
这题其实是从 ________ + ________ + ________ = 1 衍生出来的
□ □ □ □ □ □
也就是帕索大说的那个着名的题目
当初是一个同事,mail给全公司的人的一个题目
当然,公司都是一些工程师,喜欢动动脑,大家就开始解题,
我做了几分钟後,就发觉根本没有规律可言
於是就偷吃步,去跑程式
马上解出来,有6解,但事实上是同一解,因为是同一解的3!种排列
然後我把解拿给原来寄给我们的同事,验算後答案是对的
另外一个同事不太相信我能解那麽快,质问我:「你怎麽解的?」
我跟他说,我用程式去解的
後来,我对这些题目产生了兴趣,就试了几个这种题目的衍生题型
都用程式去解,有的可能有解,有的不一定有解
例如这个
□ □ □ □
________ - ________ + ________ = 0
□ □ □ □ □
此题无解,就算可以容许假分数,不一定要最简分数,放宽条件後一样无解。
而下面这题,假若不限制假分数跟最简分数的话,有20解,2者皆限制只有一解。
□ □ □ □
________ + ________ + ________ = 1
□ □ □ □ □
最後,我得到一个结论,这只是自然界的偶然现象,
你要说这其中隐藏了什麽数论的大道理,我认为没有,纯粹只是巧合而已
为了证明我所言不虚,底下附上我的程式码
有兴趣的,可以用C++ compiler来验证一下
solution代表的是第一式或第二式的解答
定义成1代表第一式的解答,2代表第二式的解答
#include "stdafx.h"
#include "iostream.h"
#include "math.h"
#include "conio.h"
#define NUMBER 9
#define solution 2
int a[NUMBER];
int head, tail;
int count;
bool flag;
void print(int n);
int main(int argc, char* argv[])
{
for(int i=0;i<NUMBER;i++)
a[i] = i+1;
count=0;
print(NUMBER);
cout << "\nTotal solutions:" << count << "\n";
return 0;
}
void swap(int &a, int& b)
{
int temp = a;
a = b;
b = temp;
}
unsigned int get_gcd(unsigned int a, unsigned int b)
{
if(a==0 || b==0)
return 0;
unsigned int quotient, remain=(a<b) ?a :b;
while(remain!=0)
{
quotient = a/b;
remain = a - quotient*b;
a = b;
b = remain;
}
return a;
}
void print(int n)
{
if(n==1)
{
flag = false;
unsigned int part_a, part_b, part_c, part_d, part_e, part_f;
unsigned int answer;
#if solution==1
part_a = a[0];
part_b = 10*a[1]+a[2];
part_c = a[3];
part_d = 10*a[4]+a[5];
part_e = a[6];
part_f = 10*a[7]+a[8];
#else if solution==2
part_a = a[0];
part_b = a[1];
part_c = 10*a[2]+a[3];
part_d = 10*a[4]+a[5];
part_e = a[6];
part_f = 10*a[7]+a[8];
#endif
answer = part_a*part_d*part_f - part_c*part_b*part_f + part_e*part_b*part_d;
unsigned gcd1 = get_gcd(part_a, part_b);
unsigned gcd2 = get_gcd(part_c, part_d);
unsigned gcd3 = get_gcd(part_e, part_f);
if(answer==0 && part_a<part_b && part_c<part_d && part_e<part_f && gcd1==1 && gcd2==1 && gcd3==1)
{
flag=true;
}
if(flag)
{
count++;
#if solution==1
cout << a[0] << "/" << a[1] << a[2] << " - ";
cout << a[3] << "/" << a[4] << a[5] << " + ";
cout << a[6] << "/" << a[7] << a[8] << " = " << " 0 ";
cout<<"\n";
#else if solution==2
cout << a[0] << "/" << a[1] << " - ";
cout << a[2] << a[3] << "/" << a[4] << a[5] << " + ";
cout << a[6] << "/" << a[7] << a[8] << " = " << " 0 ";
cout<<"\n";
#endif
}
return;
}
for(int j = 0; j<n;j++)
{
print(n-1);
if(j<n-1)
{
int index = NUMBER-j-1;
head = NUMBER-n;
tail = NUMBER-1;
swap(a[head], a[index]);
head++;
for(int k=0;k<n/2;k++)
{
swap(a[head], a[tail]);
head++;
tail--;
}
}
}
}
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 58.115.136.209
※ 编辑: utomaya 来自: 58.115.136.209 (07/08 13:51)
1F:推 puzzlez:靠推理还是可能找出全解的...至少我是这麽相信^^" 07/08 13:52
2F:推 puzzlez:那个经典题可否用推理来推算?答案是肯定的,即使它不规则 07/08 13:54
※ 编辑: utomaya 来自: 58.115.136.209 (07/08 14:54)
4F:推 fredgo:哈哈 被抓包了XD 其实是看到很多这种题目 不过总是会怀疑 07/08 16:53
5F:→ fredgo:是否有解 所以就写了一个专门写这类问题的程式啦^^a 07/08 16:53
6F:→ fredgo:不过我是用fortran写的 有空看看逻辑程序一样不一样^^ 07/08 16:55
※ 编辑: utomaya 来自: 58.115.136.209 (07/10 22:00)