SPOJ - MKEQUAL - Make them equal !

https://vjudge.net/problem/SP...

一句话题意:一个数组,n个正整数元素,每次选两个不同的元素,分别一增一减,求最后最多能得到多少个相同的元素。

比如,1 2 3 4 => 1 3 3 3,就是选2 4两个元素分别增减的结果。这时,有三个元素相同,达到了这个例子的最大值。

这个题目我觉得题面有坑……我一开始读了好几遍都不懂。而详细描述请参考原题。

原题核心描述是这样的:

At any move, you choose two indices i and j ( 0 <= i, j < N and i != j ) and increment value at one index and decrement value at other index.

这里的incrementdecrement怎么想也不应该用名词形式吧?……还是我孤陋寡闻了?求指教…

2017-02-19更新:

incrementdecrement在计算机科学中,有动词用法,其义为增/减。题目是正确的。

辞书来源为webliohttp://ejje.weblio.jp/content...


解:一增一减之后,数组元素总和不会变。所以,一个数组的元素达到多少个相同,应与元素总和有关!

再进一步思考,要想相同的元素最多,其实就是想把这个元素总和“更平均地分给所有的元素”。这就要求我们尽量让每个数都通过一增一减的操作逼近元素的平均值。

所以,就有了下面的代码。

//AC,30ms
#include<cstdio>
#define LL long long
using namespace std;
int main(){
    int t,n,temp;
    scanf("%d", &t);
    while(t--){
        LL sum = 0;
        scanf("%d", &n);
        for(int i = 0;i < n;i++){
            scanf("%d", &temp);
            sum+=temp;
        }
        printf("%d\n", n-(sum%n?1:0));
    }
    return 0;
}

其核心思想是尽量平摊元素总和。若无法完全平摊,则把无法平摊的那部分,转嫁给其中的一个元素。

代码直接利用了此结论:若元素总和能被n整除,则一定能分摊,结果是n。若无法整除,剩下的n-1个数一定能变成完全一样。数学证明简单,略去。

代码简单到让人无语……这也说明了这题真的是个水题。sumlong long是出于数据范围的考虑(但是事实证明,用int仍能AC)。

有些人的代码只用了10ms就跑完了,应是用了一些io上的优化策略。如printfscanf的重写等,以后再记。


suicca
82 声望2 粉丝

为在座的各位献上一曲WHITE ALBUM (WRONG ANSWER)