Average
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2752 Accepted Submission(s): 649
Special Judge
Problem Description
n soda sitting around a round table. soda are numbered from
1 to
n and
i-th soda is adjacent to
(i+1)-th soda,
1-st soda is adjacent to
n-th soda.
Each soda has some candies in their hand. And they want to make the number of candies the same by doing some taking and giving operations. More specifically, every two adjacent soda
x and
y can do one of the following operations only once:
1.
x-th soda gives
y-th soda a candy if he has one;
2.
y-th soda gives
x-th soda a candy if he has one;
3. they just do nothing.
Now you are to determine whether it is possible and give a sequence of operations.
Input
T, indicating the number of test cases. For each test case:
The first contains an integer
n
(1≤n≤105), the number of soda.
The next line contains
n integers
a1,a2,…,an
(0≤ai≤109), where
ai denotes the candy
i-th soda has.
Output
m (0≤m≤n) in the second line denoting the number of operations needed. Then each of the following m lines contain two integers x and y (1≤x,y≤n), which means that x-th soda gives y-th soda a candy.
Sample Input
3
6
1 0 1 0 0 0
5
1 1 1 1 1
3
1 2 3
Sample Output
NO
YES
0
YES
2
2 1
3 2
//题意:
有n个人,每个人有一定的糖果,通过一些操作,问他们的糖果是否会达到相同。
操作要求:1、每次只能给出后得到一个糖果。
2、只能从与自己相邻的人那里得到或给出。
3、每人只有一次操作。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100010
#define ll long long
using namespace std;
int t,n,m,k;
int a[N];
int b[N];
int f[N];
ll sum;
int avg;
void print()
{
printf("YES\n");
int p=0;//表示要进行操作的次数
for(int i=0;i<n;i++)
{
if(f[i])//如果f[i]非0,表示要进行一次操作
p++;
}
printf("%d\n",p);
for(int i=0;i<n-1;i++)
{
if(f[i]==-1)//表示b[i]==1,(b[i]的值比平均值大1(由fun()函数可以看出))
printf("%d %d\n",i+1,i+2);//表示第(i+1)的人把自己的一个糖果给了第(i+2)的人了。
if(f[i]==1)//与上面的操作一样,只不过上面的是给出,这里是拿来。
printf("%d %d\n",i+2,i+1);//拿来也就表示是第(i+2)的人给出一个糖果给(i+1)的人
}
if(f[n-1]==-1)//其他的都平均分好了,第n个人还多一个糖果。
printf("%d 1\n",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)//如果大于1的话就证明要操作的次数大于1,不符题意。
return 0;
if(b[i]==1)//如果b[i]值为1(表示比平均值大1)
f[i]=-1;//表示它将要进行的操作(比平均值大1,就得将这个糖果给别人)
else if(b[i]==-1)//和让面的操作一样,只是值恰好相反。
f[i]=1;
b[i+1]-=f[i];//b[i+1]接受b[i]对它的操作
b[i]+=f[i];//b[i]自身进行的操作
}
for(int i=1;i<=n;i++)
{
if(b[i])//判断是否全部有相同的糖果
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()
{
int i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
a[n]=a[0];
if(sum%n!=0)
{
printf("NO\n");
continue;
}
avg=sum/n;
for(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;
}