題目名稱: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;
}