Average
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.
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.
3 6 1 0 1 0 0 0 5 1 1 1 1 1 3 1 2 3
NO YES 0 YES 2 2 1 3 2
后来浙大出题人的题解报告出来以后,才发现此题不需要考虑得这么复杂,先放上出题人的解题报告
虽然每个人既可以对他右边的人进行操作,又可以对他左边的人操作,但是因为他们围成了一个圈,你只要考虑一个人的一个方向,自然能够将左右两边的操作都囊括。所以将每个人现有的糖果数减去平均数之后,我们只需枚举第一个人对第二个人的三种操作,就可以得到最终解,因为该人只有这三种可能性。接着向右遍历一遍判断每个人的状态即可。比如说第i个人此时的差值为1,说明他手上多了一颗糖果,因为左边是已经操作过的人,所以自然将糖果给右边;若差值为-1,则代表缺一颗糖果,左边是操作过的,所以向右边拿一颗糖果;若差值为0的话则满足条件不再需要进行操作。另外,如果差值是除了这三个数以外的数一律输出“NO”,因为每两个人之间只能进行一次操作,而一次操作又只能给1颗糖,所以差值大于1颗糖的都是无解的。
另外,若起始每个人的糖果数之和没法被n整除也是无解的,即无法均分的情况。
在这里我要提一下一种导致WA的原因,即起始每个人手中的糖果数已经相同。这样的话已满足题目要求,输出“YES”和“0”即可。但是,有些人(包括我自己)可能会有另一种操作使得最终每个人手中的糖果数相同,即每个人都给右边的人一颗糖果,这样循环一圈也是满足条件的。然而,你如果这样写的话,恭喜你,收获到WA一枚。
例如
5
1 1 1 1 1
正确结果是
YES
0
理论上可行,但实际会WA的结果是
YES
1 2
2 3
3 4
4 5
5 1
好了,闲话不多说,上代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#define exp 1e-10
using namespace std;
const int N = 100005;
const int inf = 1000000000;
const int mod = 1000000007;
int s[N],s1[N],s2[N],n,u[N],v[N],k;
bool fun(int *s)
{
int i;
for(i=2;i<=n;i++)
if(s[i]==-1)
{
s[i%n+1]--;
u[k]=i%n+1;
v[k++]=i;
}
else if(s[i]==1)
{
s[i%n+1]++;
u[k]=i;
v[k++]=i%n+1;
}
else if(s[i])
break;
if(i<=n||s[1])
return false;
return true;
}
void Clear()
{
memset(u,0,sizeof(u));
memset(v,0,sizeof(v));
k=0;
}
bool all_same()
{
for(int i=1;i<=n;i++)
if(s[i]!=s[1])
return false;
return true;
}
int main()
{
int t,i;
__int64 sum;
bool flag;
scanf("%d",&t);
while(t--)
{
sum=0;flag=false;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&s[i]);
sum+=s[i];
}
if(all_same())
{
puts("YES\n0");
continue;
}
if(sum%n)
{
puts("NO");
continue;
}
for(sum/=n,i=1;i<=n;i++)
{
s[i]-=sum;s1[i]=s2[i]=s[i];
if(s[i]>2||s[i]<-2)
break;
}
if(i<=n)
{
puts("NO");
continue;
}
Clear();
s2[2]++;s2[1]--;
u[k]=1;
v[k++]=2;
if(!fun(s2))
{
Clear();
s1[2]--;
s1[1]++;
u[k]=2;
v[k++]=1;
}
else
flag=true;
if(!flag)
{
if(!fun(s1))
Clear();
else
flag=true;
}
if(!flag)
if(fun(s))
flag=true;
if(flag)
{
puts("YES");
printf("%d\n",k);
for(i=0;i<k;i++)
printf("%d %d\n",u[i],v[i]);
}
else
puts("NO");
}
return 0;
}
欢迎大家指点
菜鸟成长记