C程序题
新年晚会老师给大家分糖,手端着一盘糖,让第一个同学先拿1块糖,再把盘中的糖分1/7给他;然后让第二个同学拿2块糖,再把盘中的糖的1/7给他;第三个同学拿3块糖后,仍把盘中的糖的1/7给他。照这个办法分下去,最后一个同学自己拿完糖后,糖恰好分完,而且每个人分到的糖块数相同。问共有几人?每人分几块糖?由“最后一个同学自己拿完糖后,糖恰好分完”以及前面的条件可知,最后一个同学所拿的糖的数量刚好等于人数。
这个题应该怎么编写呢? main()
{int t=0,m,n,i,j;
for (m=6;!t;m+=6) --------> 这里M为什么以6开始???
{t=1;n=m; /*n为最后一个同学所拿到的糖的数量(即
人数),t=1假设当前n满足条件*/
for (i=m-1;(i>=1)&&t;i--)
{j=n/6+i; /*第i个同学分到的糖的数量*/------>为什么这里等于第I个的数量呢?
n=n/6*7+i; /*第i个同学分到糖之前所剩的糖的数量*/
if (j!=m) t=0; /*每个人分到的糖块数相同.不满足就退
出模拟过程对人数重新取值*/
}
}
printf ("%6d%6d\\n",m-6,m-6);
}
看到这样的解答 实在是不太看得懂 我觉得...这题既然是让计算机算的,能不动人脑就不动人脑 (被拖走
好吧,不开玩笑,不过这题有十分多的高效解法.不可能全列出来.复杂的也不列出来,只说最直观的.
其中最短的就是纸笔推出数列通项,求和列一个一元方程.这个就算了.直接把答案输出出来就行 (死
再次,可以依靠"最后一个同学所拿的糖的数量刚好等于人数"+"每个人分到的糖块数相同"+"第n个人要先拿n块糖"来入手.这几个条件综合得知,假如总共有n人,那么最后一个同学(也就是第n个同学)要拿n块糖,同时糖已分完.进一步知道,每个同学拿到的糖数都是n块.所以糖的总数是n的平方.然后再把第一个同学所拿的糖拿来列一个一元二次方程...喂喂这不又直接求出答案了么.
所以,我们换种"蠢"一点的做法来玩玩.在分析得知糖的总数是人数的平方之后,我们就穷举所有大于1的正整数的平方作为糖数,按照最直观的方式去把糖"分配"下去,看看糖分到最后是否能正好分完.如下:
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define DIVISOR 7
typedef int bool;
bool dist( int ord, int remain ) {
if ( remain == ord )
return TRUE; /* 正确分完 */
if ( remain < ord || remain % DIVISOR != ord )
return FALSE; /* 不满足分配条件 */
return dist( ord + 1, remain - ord - ( remain - ord ) / DIVISOR );
}
void main(void) {
int person = 2;
while ( dist( 1, person * person ) == FALSE )
person++;
printf( "%d", person );
}
其它的玩法还有很多...例如说可以完全无视上面的分析,硬把大于1的自然数穷举一遍,作为糖数扔进上面那递归函数去分析也可以,收敛速度会慢很多但这数字本来就小,看不出来的. = =
不用平方也不穷举,还可以通过第一个同学拿糖的情况,知道糖总数N肯定符合N = 7k + 1,其中k=1,2,3,4,...用这个条件扔进去检测也可以.
我上面的检测方法是直观的,正向的检查.反过来从最后一个同学开始检查也可以.
用递归也可以,用循环也可以.
总之办法多的是.
P.S. 其实按道理说只有1人,每人拿到1糖的结果也符合规律,只不过题目里已经出现了3,就假设人数大于等于3吧.这样在解一元二次方程的时候也可以扔掉一个解.
Have fun ^ ^ LZ的代码一如既往难以阅读...
#include <stdio.h>
#define TRUE 1
#define FALSE 0
typedef int bool;
void main( void ) {
int m, n, i, j;
bool done = FALSE;
for ( m = 6; !done; m += 6 ) { /* --------> 这里m为什么以6开始??? */
done = TRUE;
n = m; /* n为最后一个同学所拿到的糖的数量(即人数),done=TRUE假设当前n满足条件 */
for ( i = m - 1; ( i >= 1 ) && done; i-- ) {
j = n/6 + i; /* 第i个同学分到的糖的数量 ------>为什么这里等于第i个的数量呢? */
n = n/6*7 + i; /* 第i个同学分到糖之前所剩的糖的数量*/
if ( j != m )
done = FALSE; /* 每个人分到的糖块数相同.不满足就退出模拟过程对人数重新取值 */
}
}
printf ("%6d%6d\\n", m-6, m-6);
}
建议LZ以后写好代码发出来之前先用astyle把代码格式化一次...
好吧LZ你要是是在书上看到这种解法的话,发email问它作者那m的意义你就明白了.是谁告诉你的就问谁吧,这代码 =_=|| astyle是什么东东? 没用过astyle也不知道是什么的话,请善用搜索引擎
http://astyle.sourceforge.net/
是一个美化/格式化代码的小工具.开源,免费. 代码整理VC内置的巴?
ASTYLE是什么……………… 某在eclipse已經解決格式的問題...用astyle的是vim達人吧
LZ的編程習慣還是有待改善...如果是某的同學,某C會好好調教的說...
這題如red君所言,還是先有數學式表達才真正編程
始終編程只是工具,沒有數學和邏輯編程是沒有意義的 因为Eclipse的CDT在我自己上跑实在太慢,3.1和3.1.2之后我就再也没在Eclipse里用过CDT了.
JDT的话我确实是非常喜欢用Eclipse.代码格式化/重构/自动完成的功能相当不错.
推荐Astyle是因为不想假设别人用了什么IDE或者编辑器,所以推荐脱离IDE也能单独使用的格式化小工具嘛 引用第1楼august于2007-10-07 02:16发表的:
main()
{int t=0,m,n,i,j;
for (m=6;!t;m+=6) --------> 这里M为什么以6开始???
{t=1;n=m; /*n为最后一个同学所拿到的糖的数量(即
人数),t=1假设当前n满足条件*/
.......
就是问为什么以6开始?这个简单啊...因为还剩余 6份啊 6/7嘛!
页:
[1]
2