C. 用模子使之相等
每次测试的时间限制2秒
每次测试的内存限制256兆字节
输入标准输入
输出标准输出
给你一个有n个 非负数的数组a1,a2,...,an。你可以做如下操作:选择一个整数x≥2,用该数除以x时的余数替换数组中的每一个数字,即对所有1≤i≤n设ai为imodx。
判断是否有可能通过零次或多次应用该操作使数组的所有元素相等。
输入
输入由多个测试案例组成。第一行包含一个整数t(1≤t≤104)--测试案例的数量。测试用例的描述如下。
每个测试用例的第一行包含一个整数n(1≤n≤105)--数组的长度。
每个测试用例的第二行包含n个整数a1,a2,...,an(0≤ai≤109),其中ai是数组的第i个元素。
所有测试用例的n之和最多为2⋅105。
输出
对于每个测试案例,如果你能通过应用操作使列表中的所有元素相等,则打印一行YES。否则,打印NO。
你可以在任何情况下打印每个字母(例如,"YES"、"Yes"、"yes"、"yEs "都会被认为是一个肯定的答案)。
注意
在第一个测试案例中,可以应用x=3的操作,得到数组[2,2,0,2],然后应用x=2的操作,得到[0,0,0,0]。
在第二个测试案例中,所有的数字都已经相等。
在第四个测试案例中,应用x=4的操作,得到数组[1,1,1,1]。
分析:考虑特殊情况、极端情况。
(为方便,假设 a 已经从大到小排序)
如果数组中没有 1 ,一定有办法将所有元素置为 0 (按从大到小的顺序声明 k = ai ,则每次都会正好将一个元素(或相等的多个元素)置为 0 )
现数组中有若干 1 ,如果数组中有 0 ,则直接输出NO。
现考虑将所有元素置为 1 ,策略其实也相当简单——每次从大到小声明 k = ai - 1 ,就可以将每个元素置为 1 了——如果恰好有连续的两个自然数呢?此时一定没有办法满足题意,因为无论进行怎样的选取,其差值始终会保持 1 。
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
int t;
void solve()
{
int n; cin>>n;
map<int, int> mp;
for(int i=1, x;i<=n;i++) cin>>x, mp[x]=1;
if(!mp.count(1)){cout<<"YES\n";return;}
if(mp.count(0)){cout<<"NO\n";return;}
for(auto [x, _]: mp)
{
if(mp.count(x+1)) {cout<<"NO\n";return;}
}
cout<<"YES\n";
}
int main()
{
cin >> t;
while(t --)
{
solve();
}
return 0;
}