数学高手看过来!!!

分三部分:一、问题由来;二、个人分析;三、数学问题。如果您直接奔着解决数学问题来的,可以直接跳到第三部分。但为了更好的理解,建议都看一遍,或许有其他更好的解题思路。

一、问题由来

昨晚群里一网友发表一组合问题,一开始以为他要从1~160正整数中取9个出来,这样的组合有多少种。他一问有这么多组合吗?重新看了一遍问题,又以为是把1~160分成9组,这样的组合有多少种。 (⊙﹏⊙)b 后跟他交流后才明白他的意思。

用通俗一点的语言重新表达下问题:从1~160正整数中取9个数(数值可一样),分别给9个人,使9个人的数值总和为160。请问这样的组合有多少个?

二、个人分析

第一反应,数据那么大,肯定是写个程序去处理。

首先排除153以上的数字,使用遍历法,把1~152从小到大依次给前8个人。如果前8个人的数值总和sum小于160,第9个人的数值肯定是160-sum,这样的组合便为一种组合。

在写程序的时候,使用的是递归算法。为了加快处理,每个人提取数字时的循环遍历最大值imax做了一个限制。因为每个人都会提取一个数字,最小值为1,所以第x个人的imax值等于160减去前x-1个数值总和,再减去后面剩余人的个数,即imax = 160 – sum(x-1) – (9 – x)。这样就不用再去遍历总和超过160的数字了(可以看出,这些组合数比我们要算的大的多)。下面是用的C语言写的,下标是从0开始。

#include <stdio.h>
#include <stdlib.h>

#define MAX_VALUE 160
#define MAX_GROUP 9
double count = 0;
int a[MAX_GROUP];

void ResultDisplay()
{
	int i;

	printf("%12.0f: ", count);
	for(i=0;i<MAX_GROUP;i++)
		printf("%3d ",a[i]);
	printf("\n");
}
int Combination(int sum, int n)
{
	int i=1;

	if( sum>=MAX_VALUE)
		return -1;
	if(n == MAX_GROUP - 1){
		a[n] = MAX_VALUE - sum;
		count++;
		ResultDisplay();
		return 0;
	}
	for(i=1; i<=MAX_VALUE - sum - (MAX_GROUP - 1 - n);i++){
		a[n] = i;
		Combination(sum+i, n+1);
	}
}

int main(int argc, char **argv)
{
	Combination(0,0);

	system("pause");
	return (0);
}

用我的本本运行了一分钟,结果如下:

组合数已达到3万多,但前5个人还是1。这里打印耗了很多时间,如果去掉打印,结果会快N倍。去掉后运行过半小时(运行起来后,本本的风扇一直处于高速转动的状态,担心古董受不鸟,所以运行几分就暂停一小会),通过监视看到组合数达到300多亿,但第1个人的数还是1,第2个人的数字也没超过2(忘了截图,印象中还是1)。看到这样真正的天文数字,没敢再继续运行下去了,但由此推断出组合数肯定超1000亿。

PS:昨晚在群里回复说组合数肯定超1000亿。一位群管理员表现出一副很不屑和被我忽悠的样子(“1000亿?别瞎我,我输读的少”)。一向认为群管理的话会比较稳重,再说这是一个技术群。你可以怀疑我说的,我们可以一起讨论验证,但你说这样讽刺和挑衅的话,对于我来说,最好的反驳就是拿出证据放群里给他看。在打印处加了个条件中断,从99999999990(差10就1000亿)开始打印。运行了近两个小时的时间,结果终于出来了,当时已经晚上1点了,立马编辑好文字,给他回复了过去。

1000亿,第1个人还是1,零头可能都还没达到呢。。。

以上为插曲,回归正题。此数学问题提出的时候,最长运行时间仅半小时,即300多亿。当时就想有没有一个公式,能直接用公式把组合数算出来。为了直观点,就在Excel里做了几个简单点的组合,看能否找到规律和思路。如:5分为2,5分为3,5分为4,8分为4。

一开始从后面开始找规律,最后一个不用看,就看最后两个,发现如果前面所有的数之和固定,那最后两个数的和也是固定的(这是废话),那组合数为最后两个数之和,再减1。这应该很好理解,假设最后两个数之和为y,那组合分别为(1, y-1), (2, y-2), … , (y-1,1),共y-1个。再倒数第三位数在递增的时候,y在递减。看上去很有规律,但仔细去找的时候却发现都是一些等差数列的叠加啊。

换个方向吧,从前面开始找找看。如上图,8分为4中,把第1人给不同数时的组合数给列出来了。把它的公式写出来后,发现仅适合8分为4这个组合方式,其他的都算不出正确答案。

这时,想到高中时统计学的统计方法(好像是统计学吧?),就是找到第n个与n-1个的关系。

【以为文本内容含很多博客编辑器无法显示的公式,都将使用图片】

#include <stdio.h>
#include <stdlib.h>

#define MAX_VALUE 100
#define MAX_GROUP 7

double KCombination(int m, int n)
{
	double sum=0;
	int i=0;

	if(m<n){
		printf("Error!\n");
		return (-1);
	}
	if(m==n)
		return (1);
	if(n==2)
		return (m-1);
	if(n==1)
		return (1);

	for(i=m-1;i>=n-1;i--){
		sum += KCombination(i,n-1);
	}
	return sum;
}

int main(int argc, char **argv)
{
	printf("the number of the method of combination is: %.0f\n",KCombination(MAX_VALUE,MAX_GROUP));

	system("pause");
	return(0);
}

时间: 2024-10-23 19:44:51

数学高手看过来!!!的相关文章

从数学角度看最大期望(EM)算法 II

[转载请注明出处]http://www.cnblogs.com/mashiqi 2015/3/13 对于隐变量只有有限个取值(比如个)的情况,我们可以将隐变量表示为,其中且.这样表示的目的主要是为了使后面的计算方便.如果: ???????? 则我们可以把表示为: ???????? 下面,我们看看怎么得到complete-data log-likelihood: ???????? 因此,记,我们可以得到: ???????? 如果我们能求得的极大值点,则一定有 ???????? 我们就可以把当作.

一些对数学领域及数学研究的个人看法(转载自博士论坛wcboy)

转自:http://www.math.org.cn/forum.php?mod=viewthread&tid=14819&extra=&page=1 原作者: wcboy 现在的论坛质量比以前差了,大部分都是来解题问答的,而且层次较低.以前论坛中,Qullien很令人印象深刻,但愿他能在国外闯出一片天空.现在 基础数学版代数&数论子版中那几个讨论代数几何的还不错.不期望目前论坛出现很多高层次高手,高层次高手应该站在好课题上高观点讨论数学,出 现这样的网友,看他们的言论非常过

畅游一下分析数学(张凯军)

据说最新高考改革方案中的数学考试占有重要份额,由此联想到为什么"社会这样喜爱数学"这个教育问题.既然数学被民众"重视"到了如此地步,索性就让大家看看高深数学王国中一些一线城市的风貌.只要大胆和坚持,保证会有点滴收获. 面对数学的峦峰,其实所有的数学人都是数学努力进程中的无穷小量.对那些让我们崇拜与尊敬的伟大数学家们而言,当对比广博的数学同仁时,他们才是数学努力进程中的无穷大量.要想成为数学的无穷大量型人才,第一件事就是在心理上必须解除任何的“名人未解.自己无望”的悲

“我在桥上看风景,看风景的人在楼上看我”

这段时间学习编程感觉一点思路都没有,都不知道自己想要做什么.其实自己还有很多东西都没有学会.哎,心态一点都不好.于是乎,几年下午就去图书馆瞎逛了一下,随便拿了一本书,哎呀,原来是中国文化的经典<大学>,看了几页之后,有点血液沸腾的感觉,心中的迷茫感少了不少,果断的把<中庸>借回来.通过今天下午稍稍的调整了一下自己心态.感觉自己又有一些动力了. 希望自己下一阶段好好努力,踏踏实实的. 下一阶段准备学习以下的知识点: 1.正则表达式:能够在.net中使用正则表达式经行一些基础的应用 2

SEO高手在扯蛋?

真正的高手SEO你在扯蛋吗?当大家都很会扯的时候,高手扯得肯定比你疼,不是他们 蛋比较敏感,而是他们的确更用力. 当你说我是SEO时,高手肯定说现在我在做的是SEM. 当你说我是SEM时,高手肯定在说我现在在做 MKT. 你怒了:为什么你总走在我前面? 高手看着你无辜的眼神:因为你比我先说! 你说我做热词排名,高手说我在做长尾建设. 你说我在群发长尾链接,高手说我在做站内优化. 你在说我在做站内优化,高手说我在做整站架构. 你说我在做整站架构,高手说 我在做数据分析. 你说我在做数据分析,高手说

真的猛士,敢于开数学!!!!!

dp专题看得差不多了,本来是想看图论, 但是那天物理课,莫名打开了数学专题 看了一半也不太好,就先看完再说吧~ 数学专题不用markdown好难写啊 1.组合数学 UVa580 题意:一个长度为n的序列(n<=30),由若干U,L组成 有大于等于3个连续的U的序列则为危险序列 求危险序列的数量 方法一:(LRJ) f(n)=(1<<n-3) + sigma ( g(i-2)*(1<<(n-i-2) ) (i from 2 to n-2) g(i)=(1<<i)-f

错过一个订单后,吐槽下自己(顺便分享下书单),剧终版

事先啰嗦几句 1. 纯叙述分享,也当挖坟自我重新认识(大概就是把以前的经历又翻出来的意思). 2. 前面叙述有“摇尾乞怜”之嫌,所以采用分段叙述的方式,只想看创业分享的直接往下拉. 3. 故意回避了一些真实信息,也为了避免说是软文(你TM就是怕被人肉么),所以很多东西就没写了,大家就当看小说,看看,笑笑,就过去了,别太认真.或者,就当重温一下<疯狂程序猿>(我去,你这离那小说十万八千里),哦,不对,应该叫<屌丝的逆袭之路>. 4. 特意提到自己贫困的时候(其实大学有去过贵州大方威宁

SICP 习题 (1.35)解题总结

SICP 习题 1.35要求我们证明黄金切割率φ 是变换函数 x => 1+ 1/x 的不动点,然后利用这一事实通过过程fixed-point 计算出φ的值. 首先是有关函数的不动点,这个概念须要理解清晰,后面好几道题都是环绕函数不动点展开的.作者在这里设计这些习题的原因也是希望读者能够关注函数不动点. 事实上有关不动点这个东西我在做习题"1.8"的时候就认为好奇了.为什么"(x+x/y)/2"会不断逼近x的平方根呢?又为什么"(x/y2+2y)/3

Unity CG 写一个超酷的 ray-marching(shader纯代码写3D)

Unity CG 写一个超酷的 ray-marching(shader纯代码写3D) 1.其实自从看了http://www.shadertoy.com(inigo quilez为其主创始人)上的shader后,让我感到很高兴 2.更重要的是自从我接触了一个叫 inigo quilez 的shader技术后,让我觉得shader情感更深的浓厚了 3.http://www.iquilezles.org/ 哈哈,当然给大家一个崇拜的机会吧,你一定会学到你想学到的技术和秘密 哈哈,邪恶的专栏地址放送,一