(一)题目一:运动会开了 N 天,一共发出金牌 M 枚。第一天发金牌 1 枚加剩下的七分之一枚,
第二天发金牌 2 枚加剩下的七分之一枚,第 3 天发金牌 3 枚加剩下的七分之一枚,以后每天都
照此办理。到了第 N 天刚好还有金牌 N 枚,到此金牌全部发完。编程求 N 和 M。
1. 题目分析
由第一天开始发奖牌,直到某一天天数和那一天之前发放奖牌剩余数相等,则可以由
总数减去每天发的,直至某一天发完之后余下的等于那一天的天数,进而得到天数等
于那一天天数加一,而奖牌数反推相加,或者可以由倒数第二天剩余数为 n,反推。
2. 算法构造
通过提议,每一天发的等于当天天数加剩下的七分之一,反过来,知道 n 天为 n,n-1
天发完 n-1 块之后,剩余的即为 n*7/6,由此可知,每天发的应当为 6 的倍数。
方法1:由第n天向前推起,但要知道n最小取到几,由已知可知运动会天数至少为三天,
由n=2开始计算,避免了由0开始计算时,出现n=1、m=1的特殊情况,用l =j * 7 / 6 +i-1
表示i-1天发出的奖牌数等于i天发出的乘以7/6加上i-1天的天数,通过定义多个变量,使
关系明确。
方法2:由于发放牌数总是6的倍数,所以天数也是6的倍数,使用n=n+6,同样避免了
特殊情况,同时使用i、f[i]表示天数和金牌数,简化变量使用,使用f[i]=f[i+1]*7/6+i同
样表示了表示i-1天发出的奖牌数等于i天发出的乘以7/6加上i-1天的天数,只不过将i-1
变为i,使程序可读性更高。
for(i=n-1;i>=1;i--)
{
if(f[i+1]%6!=0)
break;
else
f[i]=f[i+1]*7/6+i;
}
3. 算法实现
方法 1:
#include <stdio.h>
int i, j;
int n = 2;/*运动会天数*/
int l;/*前一天的金牌剩余数*/
void main()
{
while (1==1) {
n = n + 1;
i = n;/*当天天数*/
j = n;/*当天金牌剩余数*/
/*如果总天数不对则返回到上一层循环,如果计算正常,则计算前一天的奖牌
数,如果计算到当前天数为第二天则输出结果并且停止跳出*/
while (1==1) {
int l =j * 7 / 6 +i-1;
if (l % 6 != 0) {/*判断前一天金牌剩余数是否为六的倍数*/
break;