题目名称:Average
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5353
题意:有n个soda围着坐在一张圆桌旁,第 i 个soda和第 i+1个相邻,每两个相邻的soda x, y 能做一下三个操作中的一个,并且只能操作一次:1 、x给y一个糖果,2、y给x一个糖果,3、什么都不做,,问是否最终他们的糖果能不能相等,能输出YES和步数和步骤,不能输出NO
思路:因为只能操作一次,所以我们可以先判断刚开始是否平分或是否都相等了,然后假设第一个比平均值差1个,0个和-1个,从左往右判断就行了
代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<set>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
ll a[100005],b[100005],ave; //b数组记录第i个soda和平均值的差值
ll t,n;
int main()
{
while(scanf("%lld",&t)!=EOF)
{
while(t--)
{
scanf("%lld",&n);
ll sum=0,mx=0;
for(ll i=0; i<n; i++)
{
scanf("%lld",&a[i]);
sum+=a[i];
mx=max(mx,a[i]);
}
ave=sum/n;
if(sum%n) //不能平分
printf("NO\n");
else if(mx==ave) //最大的等于平均的
printf("YES\n0\n");
else
{
a[n]=a[0];
bool gg=true;
for(int ss=-1; ss<=1; ss++) //假设第一个比平均的多ss
{
bool ok=true;
ll summ=0;
b[0]=ss;
for(int i=1; i<=n; i++)
{
b[i]=a[i]+b[i-1]-ave;
if(abs(b[i])>=2) //因为是从左往右算的,即只能和右一个s操作,所以最大只能为 1
{
ok=false;
break;
}
if(b[i]) summ++;
}
if(ok)
{
printf("YES\n");
printf("%lld\n",summ);
for(ll i=0; i<n; i++)
{
if(b[i])
{
int x=i-min(b[i],0LL),y=i+max(b[i],0LL);
printf("%lld %lld\n",x%n+1,y%n+1);
}
}
gg=false;
break;
}
}
if(gg)
printf("NO\n");
}
}
}
return 0;
}