比赛链接:https://codeforces.com/contest/1933
官解暂未放出。
质量不错的一场 D3。
CF1933D. Turtle Tenacity: Continual Mods
题意
将数组 \(a_{1..n} \ge 1\) 重排,问是否能使 \(((a_1 \mathbin {\rm mod} a_2) \mathbin {\rm mod} a_3) \cdots \mathbin {\rm mod} a_n \ne 0\)。
题解
记 \(m\) 为原数组最小值 \(\min a\)。首先若最小值唯一,只要将其放在数组首位,它将始终不变,符合要求。另外,若有一个模 \(m\) 不为零的元素,将它和 \(m\) 放在数组的前两位,即可造出一个全新的唯一最小值,符合上面的条件。
除此之外总是无解的。证明:若所有元素都是 \(m\) 的倍数,则结果也总是 \(m\) 的倍数(因为 \((xm) \mathbin {\rm mod} (ym) = (x \mathbin {\rm mod} y ) m\))。而因为至少存在两个 \(m\),至少有一个 \(m\) 被用做过模数,在这一步答案一定变为 \(0\)。
有另外一种判定方式,显然与上面是等价的:若 \(\gcd\) 的出现次数至少为两次,则说明答案为否。
代码实现
C++,$\gcd$ 判据
void solve() {
int n;
cin >> n;
vector<int> a(n);
for (int &x : a) cin >> x;
int g = a[0];
for (int x : a) g = gcd(g, x);
cout << (ranges::count(a, g) <= 1 ? "YES" : "NO") << "\n";
}
Python,$\min$ 判据
for _ in range(int(input())):
n = int(input())
a = list(map(int, input().split()))
m = min(a)
if a.count(m) == 1 or any(x % m for x in a):
print("YES")
else:
print("NO")