hdu5353
题目名称: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; }
本文版权归作者本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.