早上看到论坛上的一道题,传送门:http://topic.csdn.net/u/20110520/09/8c61ea8b-daf8-4dd4-a6d6-46a0ac1a1583.html?62246。排列组合的问题,挺有意思。就想了下,我的答案是这样的:
当然,12-16行可以写成:
更方便。但这里的重点不是这个,而是第10行的if的判断语句,原理何在?首先要明确这个语句的功能:出去上面的6重循环不是1、2、2、3、4、5 全排列的排列,即只留下1、2、2、3、4、5的全排列。接着就是交由下面的continue语句来去除满足某某条件的排列。
好,问题又来了,为什么i1+i2+i3+i4+i5+i6==17&&i1*i2*i3*i4*i5*i6==240就可以去除呢?首先我解析下我是怎么想到的:前面的和是我经过近2个小时的思考,疲惫之下躺在床上想睡午觉时想到的:1、2、2、3、4、5无论怎么换都不变的是什么?是它们和!但之后又想,单是和是不够的,比如某个数加1,另一个数又减1,和却不变。……之后又是漫长的思考,无论怎么交换顺序都不变的,想来想去,是它们的积!于是,代码测试了一下,果真成功了!我晕,原来答案是这么简单……
为什么正确呢?先看等式a*b=(a+1)(b-1)成立的条件是b=a-1,即a、b是相邻的,而如果a、b是相邻的,经过a+1、b-1操作之后还是全排列的一种情况,没有越出全排列的范畴(越出范畴是指:出现112235之类的情况)。恩,还有一个比较麻烦的,就是那两个2。两个2互换位置,依然符合这两个式,应该是比全排列的情况多才对啊!?我也想了很久,我想我们都用创造者思维来思考,而不是检验者,即我们都想着用这两条式子来写出(创造出)全部全排列,但电脑不是,它是用来检验一个排列是不是1、2、2、3、4、5的全排列,只要符合这两条式子的,都是正确的。
之后,我要写了几段代码,看用上面的两条式,比如计算1、2、2、2、3、4的全排列个数,都正确了!
所以,有下面这个一般的结论:
有n个正整数a1 、a2、a3... an,它们的和是A,积是B,则方程组
a1 + a2+ a3+... an=A ① a1 * a2* a3*... an=B ②
解的个数就是全排列了个数。
上面这个结论,严格的数学证明没想到,大概想到应该是这样的:
I、若 a1 、a2、a3... an 互不 相等,且 x1 、x2、x3...xn 是它们的一个解,那么由于方程的对称性,各个解相互交换之后还是原方程的解,结论成立。
II、若有2个的数相等,不妨设 a1 = a2 且x1、x1、x2、x3、xn 是它们的解, 由于方程的对称性,各个解相互交换之后还是原方程的解,所以解的个数个数是P(n,n)/p(2,2)