参考博客:
https://blog.csdn.net/queuelovestack/article/details/47344537
和网上博客在对待1和2谁给谁的顺序上有些变化,从而如果输入数据刚开始全部相同,他的要特殊判断,而我这种不用。。
我的:
第一个尝试什么也不动的情况。
代码:
//I - Average
#include<stdio.h>
#include<string.h>
#define MAXN 100010
typedef long long LL;
int Data[MAXN];
int Try1[MAXN],Try2[MAXN];//枚举第一个人到第二个人的两种情况,还有一种就是不变,也就是初始化状态的Data[]
int op1[MAXN],op2[MAXN];
int n;
int cnt;
LL sum,aver;
void Init()
{
for(int i=1;i<=n;i++)
{
Data[i]-=aver;
Try1[i]-=aver;
Try2[i]-=aver;
}
}
bool Judge(int Arr[])
{
int i;
bool flag=true;
for(i=2;i<=n;i++)
{
if(Arr[i]==-1)//向右边的拿一个
{
Arr[i]+=1;
Arr[i%n+1]-=1;
op1[cnt]=i%n+1;
op2[cnt++]=i;
}
else if(Arr[i]==1)//多了一个,给右边一个
{
Arr[i]-=1;
Arr[i%n+1]+=1;
op1[cnt]=i;
op2[cnt++]=i%n+1;
}
else if(Arr[i])
{
flag=false;
break;
}
}
if(!flag||Arr[1])
return false;
return true;
}
void Print(int Arr[])
{
printf("%s\n","YES");
printf("%d\n",cnt);
for(int i=0;i<cnt;i++)
printf("%d %d\n",op1[i],op2[i]);
}
int main()
{
int i;
int kase;
scanf("%d",&kase);
while(kase--)
{
memset(Data,0,sizeof(Data));
memset(Try1,0,sizeof(Try1));
memset(Try2,0,sizeof(Try2));
sum=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&Data[i]);
sum+=Data[i];
Try1[i]=Try2[i]=Data[i];
}
if(sum%n)
{
printf("%s\n","NO");
continue;
}
aver=sum/n;
Init();//预处理一下
cnt=0;
memset(op1,0,sizeof(op1));
memset(op2,0,sizeof(op2));
if(Judge(Data))//尝试一对二的第一种情况,就是什么都不动的
Print(Data);
else
{
memset(op1,0,sizeof(op1));
memset(op2,0,sizeof(op2));
Try1[1]+=1;//尝试第一个给第二个一颗糖果的情况
Try1[2]-=1;
op1[0]=2;
op2[0]=1;
cnt=1;
if(Judge(Try1))
Print(Try1);
else
{
memset(op1,0,sizeof(op1));
memset(op2,0,sizeof(op2));
Try2[1]-=1;
Try2[2]+=1;
op1[0]=1;
op2[0]=2;
cnt=1;
if(Judge(Try2))
Print(Try2);
else
printf("%s\n","NO");
}
}
}
return 0;
}