codefoces384A-Mafia心得

题目描述:One day n friends gathered together to play "Mafia". During each round of the game some player must be the supervisor and other n - 1 people take part in the game. For each person we know in how many rounds he wants to be a player, not the supervisor: the i-th person wants to play ai rounds. What is the minimum number of rounds of the "Mafia" game they need to play to let each person play at least as many rounds as they want?

输入描述:The first line contains integer n (3 ≤ n ≤ 105). The second line contains n space-separated integersa1, a2, ..., an (1 ≤ ai ≤ 109) — the i-th number in the list is the number of rounds the i-th person wants to play.

输出描述:

In a single line print a single integer — the minimum number of game rounds the friends need to let thei-th person play at least ai rounds.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin,cout streams or the %I64d specifier.

输入样例1:

3

3 2 2

输出样例1:

4

输入样例2:

4

2 2 2 2

输出样例2:

3

题目大意:有n个人玩一个游戏 每一轮游戏都需要一个裁判 其余n-1个人是玩家 现在这n个人每个人都有想当玩家的轮数a1,a2.......an 求最少需要玩多少轮能是这n个人每个人都能玩到自己想当玩家的轮数.

输入输出解释:

输入两行  第一行是n个人 第二行是这n个人每个人想当玩家的轮数

思路:

这n个人中 必然有相当玩家轮数最多的那个人 因此 要玩的轮数至少得是max(a1,a2,.....an),我们先这样分析:刚开始,所有的人想当玩家的轮数之和为:sum(a1,a2,....an),而在每一轮游戏中,都会有n-1个人相当玩家的次数减少1,也就是sum每一次游戏减少n - 1,最终经过k轮sum小于等于0,这也就是最终的状态,sum<=0,因此,我们只需要求这个k,而这个k其实很容易求,其实k = [sum / (n - 1)],其中[]是向上取整符号,当求出这个k后,我们还需要进一步判断:当k < max(ai,a2,....an)时,代表在max(a1,a2,....an)轮之前每个人想当玩家的轮数之和就小于等于0了,这是因为,当一些人相当玩家的轮数为0时,后面的每一轮其实都必要再减去n-1了,因为这些人已经不可以再减了,这就会导数在max(a1,a2,..an)轮之前sum<=0,而因为我们最少需要玩的轮数应该是max(a1,a2,....an)轮,因此,此时我们要输出的就是max(a1,a2,...an)轮。而当k >= max(a1,a2,...an)轮时,这个k就是我们要找的最小的满足使n个人都能玩到自己相当玩家轮数的轮数。这道题目整体考虑的还是数学知识,这个规律也是我列了几组数据之后发现的,总的来说,我们要求的k的公式如下:

k = max(max(a1,a2,...an),[sum / (n - 1)]);//[]为向上取整符号

代码如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 100000;
int main(void)
{
    long long int sum,Max,a[N],i,n,m;
    scanf ("%lld",&n);
    Max = -1;
    sum = 0;
    for (i = 0; i < n; i++)
    {
        scanf ("%lld",&a[i]);

//边输入每个人相当玩家的轮数边求想当玩家次数最多的玩家相当玩家的次数
        if(Max == -1 ||a[i] > Max)
        {
            Max = a[i];
        }

//边输入边求每个人相当玩家的次数之和
        sum += a[i];
    }
    m = sum / (n - 1);

//将m向上取整
    if(m * (n - 1) < sum)
    {
        m++;
    }

//将m和max(a1,a2,....an)比较,如果比max(a1,a2,....an)小,则应该玩的轮数为max(a1,a2,....an)轮,否则为m轮
    if(m < Max)
    {
        m = Max;
    }

//输出m轮
    printf ("%lld\n",m);

    return 0;
}

 

posted @ 2017-11-15 22:53  505算法小菜`  阅读(451)  评论(0编辑  收藏  举报