HDU5353 – Average(模拟递推)

Average

【题意】一堆小朋友围成一个圈,第i和小朋友有ai颗糖果,每个小朋友最多给他左右两边的一次且一颗糖果,可以不给,求最后能否使所有小朋友的糖果数量一样。

【分析】首先所有糖果总数要能除尽n,否则必然不能平分,然后求出平均数,让所有糖果减去平均数,最后目标使得所有ai为0,只要第一个小朋友的操作确定,就能递推出所有小朋友的糖果数量,如果当前a[i] = 1,则必须要给一颗糖果给i+1,如果a[i]=-1,则说明此时先借用了右边的某个糖果,所以需要把i+1的一颗给i;则操作完如果某个a[i]的绝对值超过1(2也不行,因为不能给右边的两个,而左边的已经为0,也不能给)就返回不可能;需要注意n为1的时候以及所有糖果总数为0不能给糖果,直接YES。又无耻的用了输入输出挂。

【AC CODE】109ms

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXBUF = 10000, MAXOUT = 10000, MAXN = 100000+10;
char buf[MAXBUF], *ps = buf, *pe = buf+1;
inline void rnext(){
	if(++ps == pe)
		pe = (ps = buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);
}
template <class T>
inline bool in(T &ans)
{
	ans = 0;
	T f = 1;
	if(ps == pe) return false;//EOF
	do{
		rnext();
		if('-' == *ps) f = -1;
	}while(!isdigit(*ps) && ps != pe);
	if(ps == pe) return false;//EOF
	do
	{
		ans = (ans<<1)+(ans<<3)+*ps-48;
		rnext();
	}while(isdigit(*ps) && ps != pe);
	ans *= f;
	return true;
}
char bufout[MAXOUT], outtmp[50],*pout = bufout, *pend = bufout+MAXOUT;
inline void write()
{
	fwrite(bufout,sizeof(char),pout-bufout,stdout);
	pout = bufout;
}
inline void out_char(char c){ *(pout++) = c;if(pout == pend) write();}
inline void out_str(char *s)
{
	while(*s)
	{
		*(pout++) = *(s++);
		if(pout == pend) write();
	}
}
template <class T>
inline void out_int(T x) {
	if(!x)
	{
		out_char('0');
		return;
	}
	if(x < 0) x = -x,out_char('-');
	int len = 0;
	while(x)
	{
		outtmp[len++] = x%10+48;
		x /= 10;
	}
	outtmp[len] = 0;
	for(int i = 0, j = len-1; i < j; i++,j--) swap(outtmp[i],outtmp[j]);
	out_str(outtmp);
}
int a[MAXN],b[MAXN],n,tol;
LL sum;
P ans[MAXN];

bool ok(int v)
{
	tol = 0;
	memcpy(b,a,sizeof(int)*n);
	b[0] -= v;
	b[1] += v;
	if(-1 == v) ans[tol++] = {1,0};
	else if(1 == v) ans[tol++] = {0,1};
	rep(i,1,n)
	{
		int nxt = (i+1)%n;
		if(b[i] == 1)
		{
			b[nxt]++;
			ans[tol++] = {i,nxt};
		}
		else if(b[i] == -1)
		{
			b[nxt]--;
			ans[tol++] = {nxt,i};
		}
		if(abs(b[nxt]) > 1) return false;
	}
	return true;
}
bool all_zero()
{
	rep(i,0,n) if(a[i]) return false;
	return true;
}
bool sloved()
{
	if(1 == n)
	{
		tol = 0;
		return true;
	}
	if(sum%n) return false;
	int avg = sum/n;
	rep(i,0,n) a[i] -= avg;
	if(all_zero())
	{
		tol = 0;
		return true;
	}
	if(ok(-1) || ok(0) || ok(1)) return true;
	return false;
}
int main()
{
#ifdef SHY
	freopen("d:\\1.txt", "r", stdin);
#endif
	int t;
	in(t);
	while(t--)
	{
		sum = 0;
		in(n);
		rep(i,0,n) in(a[i]), sum += a[i];
		if(!sloved()) out_str("NO\n");
		else
		{
			out_str("YES\n");
			out_int(tol),out_char('\n');
			rep(i,0,tol) out_int(ans[i].first+1),out_char(' '),out_int(ans[i].second+1),out_char('\n');
		}
	}
	write();
	return 0;
}

 

 

发表评论

邮箱地址不会被公开。 必填项已用*标注

请输入正确的验证码