SPOJ - MKEQUAL - Make them equal !
一句话题意:一个数组,n
个正整数元素,每次选两个不同的元素,分别一增一减,求最后最多能得到多少个相同的元素。
比如,1 2 3 4 => 1 3 3 3
,就是选2 4
两个元素分别增减的结果。这时,有三个元素相同,达到了这个例子的最大值。
这个题目我觉得题面有坑……我一开始读了好几遍都不懂。而详细描述请参考原题。
原题核心描述是这样的:
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.
这里的increment
和decrement
怎么想也不应该用名词形式吧?……还是我孤陋寡闻了?求指教…
2017-02-19更新:
increment
和decrement
在计算机科学中,有动词用法,其义为增/减。题目是正确的。
辞书来源为weblio
:http://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
个数一定能变成完全一样。数学证明简单,略去。
代码简单到让人无语……这也说明了这题真的是个水题。sum
用long long
是出于数据范围的考虑(但是事实证明,用int
仍能AC)。
有些人的代码只用了10ms就跑完了,应是用了一些io上的优化策略。如printf
和scanf
的重写等,以后再记。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。