Codeforces Good Bye 2022: 2023 is NEAR: C. Koxia and Number Theory
Codeforces Good Bye 2022: 2023 is NEAR: C. Koxia and Number Theory
题意:给你n个正整数\(\lbrace a_1,a_2,\dots a_n\rbrace\),问是否存在正整数x,使\(\lbrace a_1+x+a_2+x,\dots a_n+x\rbrace\)两两互质。
很显然的结论是,若\(\lbrace a_1,a_2,\dots a_n\rbrace\)有相同数字,那必然加上\(x\)后还相同,于是就不符合两两互质的条件了。这个要预先考虑。
令\(b_i=a_i+x\),令\(cnt_{i,k}=|\lbrace a| a\in \lbrace a_1,a_2,\dots a_n\rbrace, a\equiv i \pmod k\rbrace|, i\in [0,k-1]\),即原数组模k剩余i的数的数量。
我们先思考一下\(n=2\)情况。
若\(b_i, b_j\)不互质,则存在\(k\in Z^+\),使得\(k|b_i\)且\(k|b_j\),即\(b_i\equiv b_j \equiv 0 \pmod k\),所以\(a_i\equiv a_j \equiv -x \pmod k\),不妨令\(-x\equiv t \pmod k,t\in [0,k-1]\),即\(a_i\equiv a_j \equiv t \pmod k\)。
可以看出,若\(a_i\equiv a_j \equiv t \pmod k\),那\(\forall x\equiv -t\pmod k\),都会导致\(b_i, b_j\)不互质。
推广到\(n>=2\)但只看因数为\(k\)。
一组数\(\lbrace a_1,a_2,\dots a_n\rbrace\),若对\(\forall x,都存在a_i+x\equiv a_j+x \equiv 0 \pmod k\),与之等价的是对\(\forall t \in[0,k-1]\)都可以找到\(a_i\equiv a_j \equiv t \pmod k\)。即对\(\forall i \in [0,k-1], cnt_{i,k} >1\)。
我们现在可以看出若存在\(k\in Z^+, \forall i \in [0,k-1], cnt_{i,k} >1\),一定找不出符合条件的x。那反过来,若对\(\forall k\in Z^+, 总存在 i \in [0,k-1], cnt_{i,k} \leqslant1\),是否一定能找出符合条件的x?
是可以的!
首先我们想一想,使\(\forall i \in [0,k-1], cnt_{i,k} >1\)的k,最大为多少,由于\(\lbrace a_1,a_2,\dots a_n\rbrace\)至少要两两成对模k剩余相同的数,而且要填满整个模k完全剩余系,所以满足的k一定有\(2k \leqslant n\),所以所有我们只需要考虑\(k\in [1,\lfloor n/2\rfloor]\)就行了。
若对\(\forall k\in Z^+, 总存在 i \in [0,k-1], cnt_{i,k} \leqslant 1,则取\forall x\equiv i\pmod k\),在只看k这个因数时,不会发生问题。
于是我们考虑把每个符合\(cnt_{i,k} \leqslant1\)的\(i,k\)导出的同余式加入方程组,得:
是不是很像中国剩余定理的形式,唯一不同的是,中国剩余定理要满足\(k_i,k_j\)两两互质。所以我们想一下取\(k\)为\([i,\lfloor n/2\rfloor]\)的所有质数是否与取\(k\in [i,\lfloor n/2\rfloor]\)是必要的。
显然是的,因为若\(k=pQ,p为质数\),若有\(a_i\equiv a_j \equiv t \pmod k\),则\(k|(a_i-t), k|(a_j-t)\),即\(pQ|(a_i-t), pQ|(a_j-t)\),可得\(p|(a_i-t), p|(a_j-t)\),即\(a_i\equiv a_j \equiv t \pmod p\),所以只需要考虑质数就行了。
于是我们就可以使用中国剩余定理,求出x。
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 110;
int n, m;
LL a[N];
vector<int> primes;
bool not_pri[N];
int cnt[N];
void divide(int n)
{
for(int i=2;i<=n;i++)
{
if(!not_pri[i]) primes.push_back(i);
for(int j=0;primes[j]*i<=n;j++)
{
not_pri[primes[j]*i] = true;
if(i % primes[j]==0) break;
}
}
}
bool solve()
{
cin >> n;
map<LL, int> mp;
for(int i=0;i<n;i++) cin >> a[i];
for(int i=0;i<n;i++)
{
mp[a[i]] ++;
if(mp[a[i]] >=2) return false;
}
for(int p : primes)
{
memset(cnt, 0, sizeof cnt);
for(int i=0;i<n;i++)
cnt[a[i]%p] ++;
bool flag = true;
for(int i=0;i<p;i++)
if(cnt[i] < 2)
{
flag = false;
break;
}
if(flag) return false;
}
return true;
}
int main(void)
{
divide(100);
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T = 1;
cin >>T;
while(T --)
{
if(solve()) cout << "YES" <<'\n';
else cout << "NO" <<'\n';
}
return 0;
}

浙公网安备 33010602011771号