题目描述:
问题描述:
有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:每个小朋友都把自己的糖果分一半给左手边的孩子。
一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。
反复进行这个游戏,直到所有小朋友的糖果数都相同为止。
你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。
输入
接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)
输出
样例输入
3
2 2 4
样例输出
题意解析:
1、偶数个糖:这里偶数个糖可分为两部分分别是:
I、初始化赋值为偶数
II、老师额外分配为偶数(num++);
2、分糖:将一半的糖分给左手边的孩子:
I、简化为直接分给下一个小孩 ;
II、每个小孩的糖数分一半给下一个并且从上一个小孩那得到他的一半糖;
i)是先从别人那得到他的一半糖后,再将现在的糖数分一半给下一个人,,还是所有人先分一半糖出来,每个人都前一个人那拿走他的一半糖?(这两种计算方式结果不同,也是本题解题关键;简化后即:先 + 再 / 还是先 / 再 + );
3、判断糖数是否相等:
I、不相等,跳转到第一条第二点(1.II),向下执行,
II、相等,跳出循环,输出num;
图解2.II.i:
代码实现:
#include <stdio.h>
#define N 100
void main() {
int i, n, num = 0, a[N], t;
scanf("%d", &n);
for (i = 0; i < n; i++) {//
scanf("%d", &a[i]);
}
for (;;) {
for (i = 1; i < n; i++) {//i从1开始,表示a[0]直接判断与a[1]是否相等,跳过a[0]与a[0]比较;
if (a[0] != a[i]) {
break;//如果第一个小孩糖的数量与其他小孩糖的数量不相等,跳出for循环,往下执行
}//如果没有进入if判断语句,说明所有小孩糖数相等,for循环从1执行到n-1;
}
if (i == n) {//接上for循环,当for循环执行完了以后,进行的操作是i++,此时i = n;所以可以拿来作为结束外循环条件;
break;//跳出外层循环
}
for (i = 0; i < n; i++) {//判断是否有奇数个糖,奇数+1,偶数不变;
if (a[i] % 2 == 1) {
a[i]++;
num++;
}
}
t = a[n - 1];//下面分糖实按从后向前遍历,因此最后一个小孩的糖数在最开始就会改变,无法给第一个小孩赋值,因此需要保存下来;
for (i = n - 1; i > 0; i--) {//,分糖(除以2)、得糖(+前一个人的1/2);
a[i] = a[i] / 2 + a[i - 1] / 2;
}
a[0] = a[0] / 2 + t / 2;//给第一个同学实现分糖、得糖;
}
printf("%d", num);
}
其中,在分糖和得糖那步可以实现小的优化:
前面代码不变,在判断奇偶时让所有同学的糖数一分为二;
for ( i = 0; i < n; i++)
{
if (a[i]%2==1)
{
a[i]++;
sum++;
}
a[i] /= 2;
}
temp = a[n - 1];
for ( i = n-1; i >0; i--)
{
//a[i] = a[i] / 2 + a[i - 1] / 2;
a[i] += a[i - 1];
}
//a[0] = a[0] / 2 + temp / 2;
a[0] += temp;
}