D1. Candy Party (Easy Version)
D1. Candy Party (Easy Version)
This is the easy version of the problem. The only difference is that in this version everyone must give candies to exactly one person and receive candies from exactly one person. Note that a submission cannot pass both versions of the problem at the same time. You can make hacks only if both versions of the problem are solved.
After Zhongkao examination, Daniel and his friends are going to have a party. Everyone will come with some candies.
There will be people at the party. Initially, the -th person has candies. During the party, they will swap their candies. To do this, they will line up in an arbitrary order and everyone will do the following exactly once:
- Choose an integer () and a non-negative integer , then give his candies to the -th person. Note that one cannot give more candies than currently he has (he might receive candies from someone else before) and he cannot give candies to himself.
Daniel likes fairness, so he will be happy if and only if everyone receives candies from exactly one person. Meanwhile, his friend Tom likes average, so he will be happy if and only if all the people have the same number of candies after all swaps.
Determine whether there exists a way to swap candies, so that both Daniel and Tom will be happy after the swaps.
Input
The first line of input contains a single integer () — the number of test cases. The description of test cases follows.
The first line of each test case contains a single integer () — the number of people at the party.
The second line of each test case contains integers () — the number of candies each person has.
It is guaranteed that the sum of over all test cases does not exceed .
Output
For each test case, print "Yes" (without quotes) if exists a way to swap candies to make both Daniel and Tom happy, and print "No" (without quotes) otherwise.
You can output the answer in any case (upper or lower). For example, the strings "yEs", "yes", "Yes", and "YES" will be recognized as positive responses.
Example
input
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
output
Yes
Yes
No
Yes
No
No
Note
In the first test case:
- The first person gives candy to the third person;
- The second person gives candies to the first person;
- The third person gives candy to the second person.
Then all people have candies.
In the second test case:
- The fifth person gives candies to the first person, from now on the first person has candies;
- The first person gives candies to the third person;
- The third person gives candies to the fifth person;
- The fourth person gives candies to the second person;
- The second person gives candy to the fourth person.
Then all people have candies. Note that at first the first person cannot give candies to the third person, since he only has candy. But after the fifth person gives him candies, he can do this, because he currently has candies.
In the third test case, it's impossible for all people to have the same number of candies.
In the fourth test case, the first person gives candies to the second person, and the second person gives candies to the first person as well.
解题思路
由于最后每个人分到的糖果数量一样,因此如果那么无解。定义平均数,那么最终每个人分到的糖果数量就是。
在这个版本中要求每个人都必须给恰好一个人分糖果,同时必须收到恰好一个人的糖果,如果第个人给第个人糖果那么连一条从到的有向边,那么就会得到由若干个长度至少为的环构成的图。这是因为每个节点的出度和入度都恰好为,且没有自环。
由于每个人给出以及收到的糖果数量都是的形式,因此最终每个人都要满足,其中表示第个人给出的糖果数量,表示第个人收到的糖果数量。如果有那么只需满足,而可以取任意值。下面主要讨论的情况。
如果,那么有,对于被减数和减数都是的整次幂这种形式,模拟一下可以发现得到的结果在二进制下连续的至多有段。比如,,都是合法的结果,而,都不是合法的结果。因此在枚举时如果发现不满足这个条件,那么无解。
假设每个都满足上面的条件(一样不考虑的情况),定义由构成的集合,以及由构成的集合,如果,那么必然有解,否则无解。如果,对于中每个元素总是可以在中找到值相同的元素,并且必有,此时从到连一条有向边,权值为,表示第个人给第个人个糖果,那么就会构造出一种分发方案,每个人都恰好给一个人糖果和收到一个人的糖果,且最后每个人的糖果数量均为。
还有个细节就是还需满足每个人给出的糖果不得超过当前获得的糖果数量这个条件。这个证明其实还是比较难的,比赛的时候只要最后有那么就猜有解直接交了,没考虑到这个条件,现在来补一下证明。由于每个人给糖果的顺序可以是任意的,那么在每个环中只要选择的起点满足,那么剩下的节点由于满足,因此这个条件就得到满足。可以证明环中最大的必然满足。
选择环中最大的,此时必然有,假设第个人给第个人糖果,那么有,我们要得到
假设,那么必然有,即。
如果,
与矛盾了。
如果,
与矛盾了。
因此在每个环中选择最大的作为起点,那么在交换时每个人给出的糖果数量一定不会超过当前的糖果数量。
最后再考虑回的情况,只需插在环中任意两个点间即可,比如,那么可以构造。
另外一个细节就是如何判定某个数在二进制下连续的是否至多有段。只需判断在二进制下的个数是否不超过即可。
AC代码如下,时间复杂度为:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 2e5 + 10; 7 8 int a[N]; 9 int cnt[31]; 10 11 int lowbit(int x) { 12 return x & -x; 13 } 14 15 void solve() { 16 int n; 17 scanf("%d", &n); 18 LL m = 0; 19 for (int i = 0; i < n; i++) { 20 scanf("%d", a + i); 21 m += a[i]; 22 } 23 if (m % n) { 24 printf("NO\n"); 25 return; 26 } 27 m /= n; 28 memset(cnt, 0, sizeof(cnt)); 29 for (int i = 0; i < n; i++) { 30 if (a[i] == m) continue; 31 int x = abs(a[i] - m); 32 if (__builtin_popcount(x + lowbit(x)) > 1) { 33 printf("NO\n"); 34 return; 35 } 36 int l = __lg(lowbit(x)), r = __lg(x + lowbit(x)); 37 if (a[i] < m) cnt[l]++, cnt[r]--; // a[i] - 2^l + 2^r 38 else cnt[r]++, cnt[l]--; // a[i] - 2^r + 2^l 39 } 40 for (int i = 1; i <= 30; i++) { 41 if (cnt[i]) { 42 printf("NO\n"); 43 return; 44 } 45 } 46 printf("YES\n"); 47 } 48 49 int main() { 50 int t; 51 scanf("%d", &t); 52 while (t--) { 53 solve(); 54 } 55 56 return 0; 57 }
参考资料
Codeforces Round 896 (Div. 1, Div. 2) Editorial:https://codeforces.com/blog/entry/116642
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17701777.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-09-14 匹配价值