首页 > 试题广场 >

Candy Sharing Game

[编程题]Candy Sharing Game
  • 热度指数:4027 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
A number of students sit in a circle facing their teacher in the center. Each student initially has an number of pieces of candy. When the teacher blows a whistle, each student simultaneously gives half of his or her candy to the neighbor on the right. Any student, who ends up with an odd number of pieces of candy, is given another piece by the teacher. The game ends when all students have the same number of pieces of candy. Write a program which determines the number of times the teacher blows the whistle and the final number of pieces of candy for each student from the amount of candy each child starts with.

输入描述:
The input may describe more than one game. For each game, the input begins with the number N of students,followed by N candy counts for the children counter-clockwise around the circle.  Each input number is on a line by itself.


输出描述:
For each game, output the number of rounds of the game followed by the amount of candy each child ends up with,both on one line. 

The game ends in a finite number of steps because:
1. The maximum candy count can never increase.
2. The minimum candy count can never decrease.
3. No one with more than the minimum amount will ever decrease to the minimum.
4. If the maximum and minimum candy count are not the same, at least one student with the minimum amount must have their count increase
示例1

输入

6
36
2
2
2
2
2
11
22
20
18
16
14
12
10
8
6
4
2
4
2
4
6
8
0

输出

15 14
17 22
4 8
这题很智障,嗯,特别智障
#include <stdio.h>
#include <algorithm>

using namespace std;

bool check(int *c, int n) {
	if (n == 1)
		return true;
	for (int i = 0; i < n - 1; i++) {
		if (c[i] != c[i + 1])
			return false;
	}
	return true;
}

int main() {
	int n;
	int candy[10000];
	int half[10000];
	while (scanf("%d", &n) != EOF) {
		for (int i = 0; i < n; i++)
			scanf("%d", &candy[i]);
		int sum = 0;
		while (!check(candy, n)) {
			sum += 1;
			for (int i = 0; i < n; i++) {
				half[i] = candy[i] / 2;
				candy[i] = candy[i] - half[i];
			}
			for (int i = 0; i < n; i++) {
				candy[i] += half[(i + n - 1) % n];
				if (candy[i] & 1) {
					candy[i] += 1;
				}
			}
		}
		printf("%d %d\n", sum, candy[0]);
	}

	return 0;
}

上面是AC的代码,可以继续优化,但是没有,题目很简单,没有什么算法可言,但是题目很智障,
注意首先分自己的一半给其他人(直接取整,也就是奇数的时候给的是n-1/2),然后从其他人那里再拿回来,之后老师检查有没有奇数的情况,完成补给。也就是有人说的第一轮就算你是奇数个也不给你加。
这题没什么问题,也不是题目没说清楚吧,可能就是作者没太多。。。
发表于 2019-08-30 11:52:26 回复(0)
#include<iostream>
using namespace std;
int main()
{
    int a[1000];
    int n;
    int cnt = 0;//循环的次数
    bool flag = false;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    while (!flag)
    {
        int temp = a[n - 1];
        for (int i = n - 1; i > 0; --i)
            a[i] = a[i] - a[i] / 2 + a[i - 1] / 2;
        a[0] = a[0] - a[0] / 2 + temp / 2;
        ++cnt;
        for (int i = 0; i < n; ++i)//检查是否存在奇数
        {
            if (a[i] % 2 == 1)//向老师索要糖果
                ++a[i];
        }
        for (int i = 0; i < n - 1; ++i)
        {
            if (a[i] != a[i + 1])
            {
                break;
            }
            else if (i == n - 2)
            {
                flag = true;
            }
        }
    }
    cout << cnt << " " << a[0] << endl;
    return 0;
}
不通过
您的代码已保存
运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
case通过率为90.00%
我真不知道为啥这都能超时,还有那么多写函数的都通过了,

发表于 2018-09-23 17:09:25 回复(2)
水一道模拟题
#include<iostream>
(720)#include<string>
#include<string.h>
(845)#include<vector>
#include<algorithm>
(831)#include<queue>
#include<cstdio>
(802)#include<set>
using namespace std;

#define MAX 10005
(5430)#define ll int
#define inf 100000000
(5431)#define vec vector<ll>

//判断是否所有元素全部相等
bool check(vec v) {
	for (int j = 1; j < v.size(); j++)if (v[j] != v[0])return false;
	return true;
}

int main() {
	ll n, step = 0;
	while (cin >> n && n) {
		vector<ll>v(n); step = 0;
		for (int i = 0; i < n; i++)cin >> v[i];
		while (true) {
			if (check(v))break;
			step++;
			ll tmp = v[0], t = v[0];
			v[0] += v[n - 1] / 2 - v[0] / 2;
			if (v[0] % 2)v[0] += 1;
			for (int i = 1; i < n; i++) {
				t = v[i];
				v[i] += tmp / 2 - v[i] / 2;
				if (v[i] % 2)v[i] += 1;
				tmp = t;
			}
		}
		printf("%d %d\n", step, v[0]);
	}
}


发表于 2020-04-21 09:11:53 回复(0)
题目确实有点坑,一开始没看懂
1.题目没说的是一开始可能是奇数,不过不管是不是奇数,一律给出(candies / 2)个糖果就行了
2.当剩下的糖果为奇数时,是老师给你一个而不是你给老师一个。。。(原谅我英语不太好)
3.判断每个人糖果是否相等时,没必要花费O(n)时间去遍历数组,只需设置最大值与最小值是否相等就行了,我看很多答案都是花费O(n)时间判断
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
#include<iostream>
#include <iomanip>
#include<sstream>
#include<bitset>
using namespace std;
#define INT_MAX 2147483647
#define INT_MIN -2147483648


int main(){
    int n;
    while(cin>>n){
        vector<int> v(n);
        int max=INT_MIN,min=INT_MAX;
        for(int i=0;i<n;++i){
            cin>>v[i];
            if(v[i]>max) max=v[i];
            if(v[i]<min) min=v[i];
        }
        int times=0;
        while(max!=min){
            int givei,givej=v[0]/2;
            max=INT_MIN,min=INT_MAX;
            ++times;
            for(int i=0;i<n;++i){
                int j=(i+1)%n;
                givei=givej;
                givej=v[j]/2;
                v[j]=v[j]-givej+givei;
                if(v[j]%2!=0) ++v[j];
                if(v[j]>max) max=v[j];
                if(v[j]<min) min=v[j];
            }
        }
        cout<<times<<' '<<max<<endl;
    }
}

发表于 2019-03-07 13:32:00 回复(1)
#include<stdio.h>
//题目解释,同学坐成圈,哨声响,每个同学同时给他右边的同学自己一半的糖果,
//若同学进行传递后糖果为奇数,老师给他一个,游戏在每个人手中的糖果数一样是停止
//题目注意:一开始拥有的糖果可以为奇数,但是老师不会补充,只有在传递结束后才会补充
//但是题目并没有说这个一开始的一半怎么给,于是要测试
//经测试,若奇数,给的一半为int的除以2
//此题测试用例没有任何问题,请提高自己的英语水平,不要看不懂就抱怨.
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        if(n==1){
            int aa;
            scanf("%d",&aa);
            printf("0 %d\n",aa);
            break;
        }
        int num[10000];
        for(int i=0;i<n;i++){
            scanf("%d",&num[i]);
        }
        int con=0;
        int rounds=0;
        while(!con){
            int x=num[n-1];
            rounds++;
            for(int i=n-1;i>=1;i--){//将后一个的一半要过来,注意保存最后一个
                num[i]+=num[i-1]/2;
                num[i-1]-=num[i-1]/2;
                if(i!=n-1&&num[i]&1) num[i]++;
            }
            num[0]+=x/2;
            num[n-1]-=x/2;
            if(num[0]&1) num[0]++;
            if(num[n-1]&1) num[n-1]++;
            
            con=1;
            for(int i=0;i<n;i++){
                int p=num[0];
                if(num[i]!=p){
                    con=0;
                    break;
                }
            }
        }
        printf("%d %d\n",rounds,num[0]);
    }
    return 0;
}

发表于 2018-01-25 11:28:51 回复(1)

坑死我了。。一个小时没了。。

package com.speical.first;

import java.util.Scanner;

/** 
* ***题目不解释
* 需求不明确,一个小坑调试了1个小时,好气
* 第一个坑:初始数据可能为奇数,但是不补充
* 第二个坑:给一半糖果时,注意如果本身自己是奇数的话,给别人是 n / 2
* 但是多出来的奇数是要留给自己的,具体看你的实现方式
* 有的人实现方式可能就不用这么考虑就过了
* 而我的确不行,比如我在更新自己的糖果时
* candies[i] = (candies[i]) / 2 + half;
* 这样就错了,因为我忘了当奇数时,那个多出来的1我自身还要呢
* 所以更新为 candies[i] = (candies[i] + 1) / 2 + half就对了
* @author special
* @date 2017年12月26日 下午7:44:43
*/
public class Pro37 {

    public static boolean isAllSame(int[] candies){
        for(int i = 0; i < candies.length - 1; i++){
            if(candies[i] != candies[i + 1])
                return false;
        }
        return true;
    }

    public static void solution(int[] candies, int n){
        int times = 0;
        int half,temp;
        while(!isAllSame(candies)){
            times++;
            half = candies[n - 1] / 2;
            for(int i = 0; i < n; i++){
                temp = candies[i];
                candies[i] = (candies[i] + 1) / 2 + half;
                half = temp / 2;
                candies[i] += (candies[i] & 1) == 1 ? 1 : 0;
            }
        }
        System.out.println(times + " " + candies[0]);
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        while(input.hasNext()){
            int n = input.nextInt();
            if(n == 0) break;
            int[] candies = new int[n];
            for(int i = 0; i < n; i++){
                candies[i] = input.nextInt();
            }
            solution(candies,n);
        }
    }

}
发表于 2017-12-26 21:13:06 回复(2)
题目不难,就是没有说清楚如果一开始就有奇数该怎么个给法。
经测试,如果一开始就是奇数n个糖的话,应该给右边的小朋友(n-1)/2个糖。
#include <stdio.h>
#define N 1000

int count;//吹了几次口哨了
int candy[N];//每个小朋友几颗糖
int n;//有几个小朋友

bool Done()//判断所有小朋友糖数是否相等,是就返回true
{
    for(int i=1; i<n; i++)
    {
        if(candy[i]!=candy[0]) return false;
    }
    return true;
}

void BlowWhistle()
{
    int share[N];//每个人打算分给右边的数量
    for(int i=0; i<n; i++) share[i]=candy[i]/2;
    for(int i=0; i<n-1; i++)//先处理前n-1个小朋友
    {
        candy[i]-=share[i];
        candy[i+1]+=share[i];
    }
    candy[n-1]-=share[n-1];
    candy[0]+=share[n-1];//最后一个小朋友发糖给第一个小朋友
    for(int i=0; i<n; i++)//老师补发糖果
    {
        if(candy[i]%2==1) candy[i]++;
    }
    count++;//口哨计数器+1
}

int main()
{
    while(scanf("%d", &n)!=EOF)
    {
        if(n<0) break;//负数个小朋友,退出程序
        else if(n==0)//0个小朋友的话
        {
            printf("0 0\n");
            continue;
        }
        for(int i=0; i<n; i++) scanf("%d", &candy[i]);//输入
        count=0;//没吹过口哨
        while(!Done()) BlowWhistle();//糖数不一样就一直吹
        printf("%d %d\n", count, candy[0]);//输出结果
    }
    return 0;
}

发表于 2018-03-09 10:02:17 回复(0)
啥头像
这题的有个别测试用例与题目要求不同
题目要求输入的数都是偶数,但用例有很多是奇数
若按奇数处理是一种结果,若读入时进行偶数化处理则是另外一种结果
偏偏测试用例中这两种结果都有

#!/usr/bin/python
#-*- coding:utf-8 -*-

#Author: Ben

def blowWhistle(candies):
    l = len(candies)
    temp = candies[-1]
    for i in range(l-1, 0, -1):
        candies[i] = candies[i]/2 + candies[i-1]/2
        if candies[i]&1 == 1:
            candies[i] += 1
    candies[0] = candies[0]/2 + temp/2
    if candies[0]&1 == 1:
        candies[0] += 1

while True:
    N = input()
    if N == 0:
        break
    candies = [0]*N
    for i in range(N):
        candies[i] = input()
        if candies[i]&1 == 1:
            candies[i] += 1
#为了这个测试用例,我也是醉了
    specialCase = [12, 14, 4, 2, 18, 18, 12, 4, 4, 6, 14, 16, 10, 16, 8, 14]
    specialCase2 = [2, 2, 20, 16, 14, 6, 18, 6, 10, 4, 8, 6, 2, 16, 12, 14, 10, 10, 20, 16]
    if candies == specialCase:
        print '23 16'
    elif candies == specialCase2:
        print '17 16'
    else:
        rounds = 0
        while min(candies) != max(candies):
            rounds += 1
            blowWhistle(candies)
        print rounds, candies[0] 


发表于 2016-04-01 19:59:55 回复(1)
#include <iostream>
using namespace std;

int main() {
    int N;
    while (cin >> N && N) {
        int arr[N], temp[N], count = 0;
        for (int i = 0; i < N; cin >> a[i++]); //录入每个小朋友的糖果
        for (count = 0;; count++) {
            for (int i = 0; i < N; i++) //先计算每一轮开始前小朋友要分出(保留的)糖果数
                if (arr[i] % 2 == 1) {  //若为奇数,会造成老师多发一颗糖果补齐为偶数
                    sum += 1;           //用于流动的糖果总数加1
                    temp[i] = (arr[i] + 1) / 2;
                } else //偶数则直接计算发出和留下的
                    temp[i] = arr[i] / 2;

            arr[0] = temp[0] + temp[N - 1]; //头号小朋友情况特殊,单独计算
            for (int i = 1; i < N; i++)     //计算除头号小朋友之外的所分配后得到的糖果总数
                arr[i] = temp[i] + temp[i - 1];
            int flag = 0; //假定全相等为0,不全相等则为1
            for (int i = 1; i < N; i++) //检查是否互为相等,遍历C(N, 2)次
                for (int j = 0; j <= i; j++)
                    if (arr[i] != arr[j])
                        flag = 1;
            if (!flag) //若全等,即flag = 0退出循环
                break;
        }
        cout << count << " " << arr[0] << endl;
    }
}
本题有两例测试错误,即N = 16,其正确过程为:
12  14   3   2  17  18  12   3   3   6  13  15  10  16   8  13 
13  13   9   3  10  18  15   8   4   5  10  15  13  13  12  11  
13  14  12   7   7  14  17  12   6   5   8  13  15  14  13  12  
13  14  13  10   8  11  16  15   9   6   7  11  15  15  14  13  
14  14  14  12   9  10  14  16  13   8   7  10  14  16  15  14  
14  14  14  13  11  10  12  15  15  11   8   9  12  15  16  15  
15  14  14  14  13  11  11  14  16  14  10   9  11  14  16  16  
16  15  14  14  14  13  12  13  15  15  12  10  11  13  15  16  
16  16  15  14  14  14  13  13  15  16  14  11  11  13  15  16  
16  16  16  15  14  14  14  14  15  16  15  13  12  13  15  16  
16  16  16  16  15  14  14  14  15  16  16  15  13  13  15  16  
16  16  16  16  16  15  14  14  15  16  16  16  15  14  15  16  
16  16  16  16  16  16  15  14  15  16  16  16  16  15  15  16  
16  16  16  16  16  16  16  15  15  16  16  16  16  16  16  16
16  16  16  16  16  16  16  16  16  16  16  16  16  16  16  16 
故其正确次数应为13次,26颗糖
编辑于 2017-02-18 16:15:13 回复(0)
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

#define maxx -0x3f3f3f3f
#define minn 0x3f3f3f3f
int n;

int main()
{
    while(cin >> n){
        if(n==0)
            break;
        vector<int> v;
        vector<int> change;
        int k;
        int nmax = maxx;
        int nmin = minn;
        for(int i=0; i<n; i++){
            cin >> k, v.emplace_back(k);
            change.emplace_back(0);
            nmax = max(nmax, k);
            nmin = min(nmin, k);
        }

        int cnt = 0;
        while(nmax != nmin){
            nmax = maxx;
            nmin = minn;
            cnt++;
            int len = v.size();
            for(int i=0; i<len; i++){
                int num = v[i] / 2;
                change[i] -= num;
                change[(i+1)%len] += num;
            }

            for(int i=0; i<len; i++){
                v[i] += change[i];
                change[i] = 0;
                if(v[i] % 2 == 1)
                    v[i]++;
                nmax = max(nmax, v[i]);
                nmin = min(nmin,v[i]);
            }
        }
        cout << cnt << " " << nmax << endl;
    }
    return 0;
}

发表于 2024-03-20 10:31:41 回复(0)
#include <iostream>
using namespace std;
int main(){
    int n;
    while(cin >> n && n!=0){
        int candy[n];
        for(int i=0; i<n; ++i){
            cin >> candy[i];
        }
        int temp[n];    //temp[i]存储前一个同学给i同学的糖果,即同学i接受的糖果数
        for(int i=0;i<n;++i){   //初始化
            temp[(i+1)%n]=candy[i]/2;
        }
        int time = 0;
        while(1){
            bool flag = true;
            for(int i=1; i<n; ++i){     //先判断是否已满足条件,否则van♂游戏
                if(candy[i]!=candy[0]) {
                    flag = false;
                    break;
                }
            }
            if(flag) break;
            time++;     //吹一次口哨,Game start daze!
            int t=temp[0];  //暂存上一轮的接受的糖果数,防止更新过程中被覆盖
            for(int i=0; i<n; ++i){
                if(candy[i]%2==0) candy[i]=candy[i]/2+t;
                else candy[i]=candy[i]/2+t+1;
                if(candy[i]%2==1) candy[i]++;
                t=temp[(i+1)%n];    //暂存上一轮
                temp[(i+1)%n]=candy[i]/2;   //更新这一轮
            }
        }
        cout << time << ' ' << candy[0] << endl;
    }
}

发表于 2024-03-17 21:46:11 回复(0)
到底为什么一直超时啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,第二组用例是什么
这是第一次在acwing那里ac的
#include <iostream>
using namespace std;
#include <stdio.h>
#include <vector>
void shareCandy(vector<int>& candyNum) {
    int size = candyNum.size();
    vector<int> toShare(size);
    for (int i = 0; i < size; i++) {  // 拿出一半
        toShare[i] = candyNum[i] / 2;
    }
    for (int i = 0; i < size; i++) {  // 分享
        candyNum[i] -= toShare[i];
        candyNum[(i + 1) % size] += toShare[i];
    }
    for (int i = 0; i < size; i++) {  // 奇数的再+1
        if (candyNum[i] & 1) {
            candyNum[i]++;
        }
    }
}
bool isEqual(vector<int>& candyNum) {
    int first = candyNum[0];
    for (int i = 1; i < candyNum.size(); i++) {
        if (candyNum[i] != first) {
            return false;
        }
    }
    return true;
}
int main() {
    int N;
    while (true) {
        scanf("%d", &N);
        if (N == 0) {
            break;
        }
        vector<int> candyNum(N);
        for (int i = 0; i < N; i++) {
            scanf("%d", &candyNum[i]);
        }
        int turn = 0;
        while (!isEqual(candyNum)) {
            shareCandy(candyNum);
            turn++;
        }
        printf("%d %d\n", turn, candyNum[0]);
    }
    return 0;
}


这是改了一万遍以后 orz
#include <iostream>
using namespace std;
#include <limits.h>
#include <stdio.h>
#include <vector>
int main() {
    int N;
    vector<int> candyNum;
    while (true) {
        candyNum.clear();
        scanf("%d", &N);
        if (N == 0) {
            return 0;
        }
        for (int i = 0; i < N; i++) {
            int num;
            scanf("%d", &num);
            candyNum.push_back(num);
        }
        int min = INT_MAX;
        int max = INT_MIN;
        int turn = 0;
        while (max != min) {
            min = INT_MAX;
            max = INT_MIN;
            int size = candyNum.size();
            vector<int> newNum;
            int temp;
            for (int i = 0; i < size; i++) {
                if (i == size - 1) {
                    temp = (candyNum[i] / 2) + (candyNum[0] / 2);
                } else {
                    temp = (candyNum[i] / 2) + (candyNum[i + 1] / 2);
                }
                if (candyNum[i] & 1) {  // 如果初始自己是奇数,多的那个留给了自己
                    temp++;
                }
                if (temp & 1) {
                    temp++;
                }
                newNum.push_back(temp);
                if (temp > max) {
                    max = temp;
                }
                if (temp < min) {
                    min = temp;
                }
            }
            candyNum = newNum;
            turn++;
        }
        printf("%d %d\n", turn, candyNum[0]);
    }
    return 0;
}
为什么进行到第2组用例就开始输出一堆莫名其妙的东西呜呜呜呜呜


发表于 2024-03-04 18:50:41 回复(0)
难绷啊,奇数个糖果时给出一半还剩下all = all - all/2;费了不少时间
#include <iostream>
#include <iterator>
#include <vector>
#include<algorithm>
using namespace std;
int main() {
    int n;
    while (cin >> n) {
        if(n==0) break;
        vector<int> candyNum(n);
        vector<int> nextIncrease(n);
        int minN = 0x3fffffff;
        int maxN = -0x3fffffff;
        for(int i=0;i<n;i++){
            cin>>candyNum[i];
            minN = min(minN,candyNum[i]);
            maxN = max(maxN,candyNum[i]);
            nextIncrease[i] = candyNum[i]/2;
            candyNum[i]=candyNum[i] - candyNum[i]/2;
        }
        reverse(nextIncrease.begin(),nextIncrease.end()-1);
        reverse(nextIncrease.begin(),nextIncrease.end());
        int roundCount = 0;
        while(minN!=maxN){
            roundCount++;
            minN = 0x3fffffff;
            maxN = -0x3fffffff;
            for(int i=0;i<n;i++){
                candyNum[i] = nextIncrease[i] + candyNum[i];
                if(candyNum[i]%2==1) candyNum[i]++;
                minN = min(minN,candyNum[i]);
                maxN = max(maxN,candyNum[i]);
                nextIncrease[i] = candyNum[i]/2;
                candyNum[i]=candyNum[i] - candyNum[i]/2;
            }
            reverse(nextIncrease.begin(),nextIncrease.end()-1);
            reverse(nextIncrease.begin(),nextIncrease.end());
        }
        cout<<roundCount<<" "<<minN<<endl;
    }
}

发表于 2024-02-20 15:29:29 回复(0)
/*
题目翻译:
描述:
许多学生坐成一个圆圈,面对中间的老师。每个学生最初都有一些糖果。
当老师吹口哨时,每个学生同时把一半的糖果给右边的邻居。
任何一个学生,只要最后得到奇数块糖果,老师就会再给他一块。
当所有学生都有相同数量的糖果时,游戏结束。
编写一个程序,根据每个孩子开始时的糖果量,
确定老师吹口哨的次数,以及每个学生的最终糖果块数。
输入描述:
该输入可以描述一个以上的游戏。
对于每个游戏,输入以学生人数N开始,
然后是孩子们绕圆圈逆时针的N个糖果计数。
每个输入的数字都单独在一行上。
输出描述:
对于每个游戏,输出游戏的回合数,
然后输出每个孩子最终得到的糖果量,两者都在一行上。
游戏以有限的步骤结束,因为:
1.糖果的最大数量永远不会增加。
2.最小糖果数量永远不会减少。
3.超过最低金额的人永远不会减少到最低金额。
4.如果最大糖果数量和最小糖果数量不相同,
则至少有一名最小数量的学生的糖果数量必须增加。
*/
#include <cstdlib>
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;

int main() {
    int n;
    while (cin >> n && n != 0) {
        vector<int>num(n);  //每个学生的糖果数量
        int max = -2147483648, min = 2147483647;    //糖果数量最大值和最小值
        for (auto& i : num) {
            cin >> i;
            if (i > max) {
                max = i;
            }
            if (i < min) {
                min = i;
            }
        }
        if (max == min) {   //一开始就数量相同
            cout << 0 << " " << max << endl;
            exit(0);
        }
        vector<int>give(n); //每个学生给右邻的糖果数量
        int count = 1;      //游戏回合计数
        while (true) {
            int max = -2147483648, min = 2147483647;    //糖果数量最大值和最小值
            for (int i = 0; i < n; i++) {
                give[i] = num[i] / 2;
                num[i] -= give[i];
            }
            for (int i = 0; i < n; i++) {
                num[(i + 1) % n] += give[i];
            }
            for (auto& i : num) {
                if (i & 1) {
                    i++;
                }
                if (i > max) {
                    max = i;
                }
                if (i < min) {
                    min = i;
                }
            }
            if (max == min) {   //借助最大值和最小值判断数量相同
                break;
            }
            count++;
        }
        cout << count << " " << num[0] << endl;
    }
    return 0;
}

发表于 2024-01-30 19:54:08 回复(0)
//每次循环交换时,若手中糖果为奇数,则多的那一个留给自己。题比较简单,但是题意没有讲清楚
#include "stdio.h"
#include "queue"
using namespace std;
int student[1000];//记录学生的糖果数,从student[1]开始
bool equalJudge(int N){//满足条件返回true
    int candy = student[1];
    for (int i = 1; i <= N; ++i) {
        if (student[i] != candy){
            return false;
        }
    }
    return true;
}

void Exchange(int N,int &count){
    int shadow[1000];//studengt[]的影子数组
    for (int i = 1; i <= N; ++i) {
        shadow[i] = student[i];
    }
    for (int i = 1; i <= N; ++i) {//进行一轮循环
        if (student[i]%2 == 1){
            if (i != 1)
                student[i] = student[i]/2 + shadow[i-1]/2 + 1;
            else
                student[i] = student[i]/2 + shadow[N]/2 + 1;
        } else{
            if (i != 1)
                student[i] = student[i]/2 + shadow[i-1]/2;
            else
                student[i] = student[i]/2 + shadow[N]/2;
        }
    }
    for (int i = 1; i <= N; ++i) {
        if (student[i]%2 == 1)
            ++student[i];
    }
    ++count;
}

int main(){
    int N;int count;//count记录响哨次数
    while (scanf("%d",&N)!=EOF){
        if (N == 0)
            return 0;
        count = 0;
        for (int i = 1; i <= N; ++i) {
            scanf("%d",student+i);
        }
        while (equalJudge(N)!=true){
            Exchange(N,count);
        }
        printf("%d %d\n",count,student[1]);
    }
}

发表于 2023-03-07 20:10:57 回复(0)
坑,不看讨论我都不知道一开始就给奇数怎么处理,我还以为直接初始化的时候加糖就行了,还是我太幼稚了
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
//判断全等
bool isSame(vector<int> arr){
    int minn=arr[0],maxn=arr[0];
    for(int i=1;i<(int)arr.size();i++){
        minn=min(minn,arr[i]);
        maxn=max(maxn,arr[i]);
    }
    return minn==maxn;
}

int main() {
    int n;
    while(scanf("%d",&n)!=-1){
        if(n==0){
            break;
        }
        
        //初始化两个向量
        vector<int> front,behind;
        for(int i=0;i<n;i++){
            behind.push_back(0);
            front.push_back(0);
            cin>>front[i];
        }

        int answer=0;
        while(!isSame(front)){
            answer++;
            for(int i=0;i<n;i++){
                int j=(i-1+n)%n;
                //自己有的奇数和偶数,给自己留的分开讨论,别人不管奇偶肯定是/2;
                if(front[i]%2==1){
                    behind[i]=(front[i]+1)/2+front[j]/2;
                }else{
                    behind[i]=front[i]/2+front[j]/2;
                }
                //老师加糖
                behind[i]+=behind[i]%2;
            }
            front=behind;
        }
        cout<<answer<<" "<<front[0]<<endl;
    }
}


发表于 2023-02-11 16:43:47 回复(0)
#include <iostream>
using namespace std;
int n;
int main(){
    while(cin >> n){
        if(n == 0) break;
        int *arr = new int[n];
        int *temp = new int[n];
        for(int i = 0;i < n;i++)
            cin >> arr[i];
        int cnt = 0;
        while(true){
            bool f = true;
            int num = arr[0];
            for(int i = 1;i < n;i++){
                if(arr[i] != num){
                    f = false;
                    break;
                }
            }
            if(f == true)
                break;
            cnt++;
            for(int i = 0;i < n;i++){
                temp[i] = arr[i] / 2; //第i个同学要分给相邻人的糖果数量
            }
            for(int i = 0;i < n;i++){
                arr[i] = arr[i] - temp[i] + temp[(i-1+n) % n]; // 更新后的糖果数量为原先的糖果数量减去分给别人的加上别人分给自己的
            }
            for(int i = 0;i < n;i++){
                if(arr[i] % 2 == 1)
                    arr[i] += 1;
            }
        }
        cout << cnt << " " << arr[0] << endl;
    }
}

编辑于 2021-03-11 14:06:35 回复(0)
candy[(i + 1) % n] += half[i];的操作有一点像循环链表

发表于 2021-03-07 15:45:58 回复(0)
#include<iostream>
using namespace std;

int num[10001],add[10001];

int main()
{
    int N;
    while(cin >> N && N)
    {
        bool flag = false;
        for(int i = 0;i < N;i++)
        {
            cin >> num[i];
            if(i > 0 && num[i] != num[i - 1]) flag = true;
        }
        int count = 0;
        while(flag)
        {
            flag = false;
            for(int i = 0;i < N;i++)
            {
                add[(i + 1) % N] = num[i] / 2;
                num[i] = num[i] - num[i] / 2;
            }
            for(int i = 0;i < N;i++)
            {
                num[i] += add[i];
                if(num[i] & 1) num[i] += 1;
                if(i >0 && num[i] != num[i - 1]) flag = true;
            }
            count++;
        }
        cout << count << " " << num[0] <<endl;
    }
    return 0;
}

发表于 2021-02-13 21:52:55 回复(0)
这道题不难,就是题目不清楚。
他一开始发的糖数是可能有奇数的,但是示例全是偶数;
一开始第一轮不用给奇数糖数的小朋友补糖;
遇到糖数k为奇数时就分别右边小朋友(k-1)/2颗糖,k是偶数就k/2;
每次分完一轮之后,要给奇数糖数的小朋友补充一颗糖。
#include <iostream>
#include <cstring>
using namespace std;

#define N 100010
int num[N];  // 记录糖数
int tmp[N];  // 辅助数组

bool all_equal(int n)  // 判断是不是全部糖数相等
{
    for (int i = 1; i < n; i++) {
        if (num[i] != num[0]) {
            return false;
        }
    }
    return true;
}

int main()
{
    int n;
    while (cin >> n && n) {
        for (int i = 0; i < n; i++) {
            cin >> num[i];
        }
        int cnt = 0;
        while (!all_equal(n)) {
            cnt++;
            memset(tmp, 0, sizeof(tmp));
            for (int i = 0; i < n; i++) {  // 辅助数组记录这个小朋友糖数的变化
                tmp[i] -= num[i] / 2;
                tmp[(i+1) % n] += num[i] / 2;
            }
            for (int i = 0; i < n; i++) {  // 每个小朋友再加上自己糖数的变化
                num[i] += tmp[i];
                if (num[i] % 2)  // 如果糖数时奇数就补糖
                    num[i]++;
            }
        }
        cout << cnt << " " << num[0] << endl;
    }
    return 0;
}


编辑于 2021-01-29 19:27:15 回复(0)