一句话题意:一个数组,n
个正整数元素,每次选两个不一样的元素,分别一增一减,求最后最多能获得多少个相同的元素。数组
好比,1 2 3 4 => 1 3 3 3
,就是选2 4
两个元素分别增减的结果。这时,有三个元素相同,达到了这个例子的最大值。优化
这个题目我以为题面有坑……我一开始读了好几遍都不懂。而详细描述请参考原题。spa
原题核心描述是这样的:.net
At any move, you choose two indices
i
andj
(0 <= i, j < N and i != j
) and increment value at one index and decrement value at other index.code
这里的increment
和decrement
怎么想也不该该用名词形式吧?……仍是我孤陋寡闻了?求指教…rem
2017-02-19更新:get
increment
和decrement
在计算机科学中,有动词用法,其义为增/减。题目是正确的。数学
辞书来源为weblio
:http://ejje.weblio.jp/content...io
解:一增一减
以后,数组元素总和不会变。因此,一个数组的元素达到多少个相同,应与元素总和有关!
再进一步思考,要想相同的元素最多,其实就是想把这个元素总和
“更平均地分给全部的元素”。这就要求咱们尽可能让每一个数都经过一增一减
的操做逼近元素的平均值。
因此,就有了下面的代码。
//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
个数必定能变成彻底同样。数学证实简单,略去。
代码简单到让人无语……这也说明了这题真的是个水题。sum
用long long
是出于数据范围的考虑(可是事实证实,用int
仍能AC)。
有些人的代码只用了10ms就跑完了,应是用了一些io上的优化策略。如printf
和scanf
的重写等,之后再记。