D1. Candy Party (Easy Version)(构造规律)

Problem - D1 - Codeforces

这是问题的简化版本。唯一的区别是,在该版本中,每个人必须给一个人糖果,并从一个人那里接收糖果。请注意,一次性提交不能同时通过问题的两个版本。只有在解决了问题的两个版本后,才能进行黑客攻击。

在中考之后,丹尼尔和他的朋友们要举办一个派对。每个人都会带一些糖果来。

派对上会有n个人。初始时,第i个人有ai个糖果。派对期间,他们将交换他们的糖果。为此,他们将以任意顺序排队,并且每个人仅执行以下操作一次:

 
 

Plain Text

 
 
选择一个整数p(1≤p≤n)和一个非负整数x,然后将他的2x个糖果给第p个人。请注意,不能给出比他当前拥有的糖果更多的糖果(他之前可能从其他人那里接收到糖果),也不能把糖果给自己。

丹尼尔喜欢公平,所以只有当每个人都从一个人那里接收到糖果时他才会开心。与此同时,他的朋友汤姆喜欢均等,所以只有当所有人在全部交换后拥有相同数量的糖果时他才会开心。

确定是否存在一种交换糖果的方法,以使得丹尼尔和汤姆在交换后都会开心。 输入

输入的第一行包含一个整数t(1≤t≤1000) - 测试用例的数量。后续是描述每个测试用例的行。

每个测试用例的第一行包含一个整数n(2≤n≤2⋅105) - 派对上的人数。

每个测试用例的第二行包含n个整数a1,a2,…,an(1≤ai≤109) - 每个人拥有的糖果数量。

保证所有测试用例中n的总和不超过2⋅105。 输出

对于每个测试用例,如果存在一种交换糖果的方式使得丹尼尔和汤姆都开心,请打印"Yes"(不带引号),否则打印"No"(不带引号)。

您可以输出答案的任何大小写形式。例如,字符串"yEs"、"yes"、"Yes"和"YES"都将被识别为肯定回答。 示例 输入 复制

6 3 2 4 3 5 1 2 3 4 5 6 1 4 7 1 5 4 2 20092043 20092043 12 9 9 8 2 4 4 3 5 1 1 1 1 6 2 12 7 16 11 12

输出 复制

Yes Yes No Yes No No

注意

第一个测试用例中:

 
 

Plain Text

 
 
第一个人给第三个人1个糖果;
第二个人给第一个人2个糖果;
第三个人给第二个人1个糖果。

然后所有人都有3个糖果。

第二个测试用例中:

 
 

Plain Text

 
 
第五个人给第一个人4个糖果,此时第一个人有5个糖果;
第一个人给第三个人2个糖果;
第三个人给第五个人2个糖果;
第四个人给第二个人2个糖果;
第二个人给第四个人1个糖果。

然后所有人都有3个糖果。注意,刚开始时第一个人不能给第三个人2个糖果,因为他只有a1=1个糖果。但是在第五个人给他4个糖果之后,他就可以这样做了,因为他目前有1+4=5个糖果。

第三个测试用例中,所有人都拥有相同数量的糖果是不可能的。

第四个测试用例中,第一个人给第二个人1024个糖果,同时第二个人也给第一个人1024个糖果。

题解:

题目中说每个人一定要接受2^?的礼物,那么肯定每个人也会给出去2^?的礼物

如果总和无法被平均直接输出NO

否则应该满足a[i] - 2^q + 2^p = x

x为平均值

我们变一下形 2^p - 2^q = a[i] - x

右边为一个固定的值w,这时候牵扯到一个规律

假设这个值成立,那么肯定有唯一确定的p和q导致其成立,

证明:
10000..p个0 - 10000q个0 均是二进制位

最后的结果形式一定是1111...0....这样的形式

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> PII;
multiset<int> s; 
const int N = 5e5 + 10;
int a[N];
void solve()
{
	int n;
	cin >> n;
	int s = 0;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i];
		s += a[i];
	} 
	if(s%n != 0)
	{
		cout <<"NO\n";
		return ;
	}
	s /= n;
	int f = 1;
	vector<int> u(100),v(100);
	for(int i = 1;i <= n;i++)
	{
		f = 1;
		for(int j = 0;j < 40;j++)
		{
			for(int k = 0;k < 40;k++)
			{
				if(a[i] - (1ll << j) + (1ll << k) == s&&f)
				{
					u[j]++;
					v[k]++;
					f = 0;
					break;
				}
			}
		}
		if(f)
		{
			cout <<"NO\n";
			return ;
		}
	}
	if(u == v)
	{
		cout <<"YES\n";
	} 
	else
	{
		cout <<"NO\n";
	}
} 
signed main()
{
	int t = 1;
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t ;	
	while(t--)
	{
		solve();
	}
}
//环

猜你喜欢

转载自blog.csdn.net/m0_64158084/article/details/132832213