官方题解:http://bestcoder.hdu.edu.cn/blog/
HDOJ5355、5360、5363超过300人AC,思路见官方题解
比赛时5353一直WA,2小时后发现队友5360居然还没做出来,orz,于是花了20+分钟把这题1Y
5355比赛SPJ写错,基本大家不CE,都能AC
HDOJ5353
题意:有n个人坐成一圈,每人有m个糖果,每对相邻的人可以进行一次给一个糖果的操作,问能否均分糖果,能的话输出所有操作,x给y一个糖果
思路:先把不能整除的情况特判掉,再把所有数扣掉平均数方便后面操作,特判n<3的情况,最后再开始处理一般情况。
每对相邻的人一共三种情况:给、不变、拿,暴力第一对人的所以情况,之后后面每一对人的操作也就确定了
注意:全为0的情况,要输出YES 0,就因为这个一直WA。。。原先代码是先算fun(-1)再算fun(0)。。。。调换位置就AC了
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <vector> using namespace std; typedef long long LL; const int MAXN=1e5+10; int T,n,m,k; int a[MAXN],b[MAXN],f[MAXN]; LL sum; int avg; void init(){ sum=0; for(int i=0;i<n;i++){ scanf("%d",&a[i]); sum+=a[i]; } a[n]=a[0]; } void print(){ printf("YES\n"); int p=0; for(int i=0;i<n;i++){ if(f[i]!=0)p++; } printf("%d\n",p); for(int i=0;i<n-1;i++){ if(f[i]==-1){ printf("%d %d\n",i+1,i+2); } if(f[i]==1){ printf("%d %d\n",i+2,i+1); } } if(f[n-1]==-1){ printf("%d 1\n",n); } if(f[n-1]==1){ printf("1 %d\n",n); } } bool fun(int x){ memset(f,0,sizeof(f)); for(int i=0;i<=n;i++){ b[i]=a[i]; } f[0]=x; b[1]-=f[0]; b[0]+=f[0]; b[n]=b[0]; for(int i=1;i<n;i++){ if(abs(b[i])>=2)return 0; if(b[i]==1){ f[i]=-1; }else if(b[i]==-1){ f[i]=1; } b[i+1]-=f[i]; b[i]+=f[i]; } for(int i=1;i<=n;i++){ if(b[i]!=0)return 0; } return 1; } void work(){ if(fun(0)){print();return;} if(fun(-1)){print();return;} if(fun(1)){print();return;} printf("NO\n"); return; } int main(){ #ifdef DEBUG freopen("CBin.txt","r",stdin); //freopen("CBout.txt","w",stdout); #endif scanf("%d",&T); while(T--){ scanf("%d",&n); init(); if(sum%n!=0){ printf("NO\n"); continue; } avg=sum/n; for(int i=0;i<n;i++){ a[i]-=avg; } a[n]=a[0]; if(n==2||n==1){ if(fun(0))print(); else printf("NO\n"); }else work(); } return 0; }