0%

CF99b题解

蒟蒻的第一篇题解。

这个题还是特别水的,但我就被淹死了

读题

给了你一个数组,让你将其中一个数的一部分给另一个数,使所有数相等,只操作一次。当我们一看到只操作一次 ,就会很自然而然地想到:
就只有两个数不一样。
所以我们就可以在这里下功夫。
而改变之后所有数相同,所以平均数就是所有数的数值。

所以出现最多的数一定与平均数相同 ,并且,如果可以移动,剩下的两个数的平均数也一定与之相同 。

我们就可以先判断整个数组的和能不能被数组大小 $n$ 整除,如果能,证明所有数的平均数就是 $sum/n$,如果不能的话操作一定不成立
如果平均数可以求出,那么这一组数就可以用多次操作使所有数相同。

那怎样才能判断操作一次呢?
操作一次只能改变两个数,那么与出现最多的数不同的数只能有两个。
那怎么判断这些数中出现最多的数的呢?
我们会首先想到桶排。也不是不行,就是太浪费了,并且这水题也不足以用桶排,我们就又想起刚刚想到的:
只有两个数不一样,其他数都等于平均数 ,所以我们只需要统计与平均数不同的个数即可。

之后按照题目要求给出输出即可,千万别打错了

$code$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<iostream>
using namespace std;
int f[1001];
int flag;//与平均数不同的数字个数
struct node{//可以同时记录最大最小的数值和对应下标
int num;//下标记录
int data;//数据记录
};
node maxn,minn={0,0x3f3f3f};//将最小值的数据初始化为一个非常大的数,防止出错
int sum;
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>f[i];
sum+=f[i];
if(maxn.data<f[i]){
maxn.data=f[i];
maxn.num=i;
}
if(minn.data>f[i]){
minn.data=f[i];
minn.num=i;
}
}//找最大和最小,求和,这里推荐写代码时把能合的for循环全部合起来,不仅能使码量更少,还能更快那么一点点
if(sum%n!=0) {
cout<<"Unrecoverable configuration.";//无法整除那么一定不能实现题目要求
return 0;}
else{
int pj=sum/n;
for(int i=0;i<n;i++){
if(f[i]!=pj) flag++;
}
if(flag==0) {
cout<<"Exemplary pages.\n";//如果平均数不同的数字个数为0,就是所有数字都一样 输出
return 0;}
else if(flag>2) {
cout<<"Unrecoverable configuration.\n";//如果与平均数不同的数超过2个,输出,注意是>而不是>=
return 0;}
else{
printf("%d ml. from cup #%d to cup #%d.\n",(maxn.data-minn.data)/2,minn.num+1,maxn.num+1);//我的数组下标从0开始,所以要加1
//这里有个坑点,要从先输出杯中水少的再输出水多的 不要搞反了
//还有倒水时是将一个杯子里的水倒入另一个,所以两个一个增加一个减少,要除以2
return 0;
}
}
return 0;//over
}