Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Prefix GCD arrays have a very rigid shape: must be divisible by . Suffix GCD arrays are rigid in the other direction: must be divisible by . If either fails, the answer is instantly No.
For any real array , the value must be divisible by both and , because belongs to both the prefix ending at and the suffix starting at .
So the “smallest reasonable” candidate is . If any solution exists, every valid is a multiple of this .
Now test the candidate directly: compute the prefix GCD array of and the suffix GCD array of . If they match and , then itself is a valid array.
The key proof is two-sided: if a valid exists, then divides , so the GCDs of cannot be too large; and divisibility monotonicity of and guarantees they cannot be too small. So checking is both necessary and sufficient.
We need decide whether some hidden array could produce the given prefix GCDs and suffix GCDs .
The tempting wrong move is to try to reconstruct greedily. Don't. GCD constraints are nasty if you poke them directly, but they become clean if you build the smallest forced value at every position.
What must be true about one position?
If , then divides every element among , especially .
If , then divides every element among , especially .
So every valid must be divisible by both and . Therefore it must be divisible by
This gives us a very natural candidate array . The claim is:
There exists a valid array if and only if the array has prefix GCDs exactly and suffix GCDs exactly .
So the algorithm is stupidly simple in the best way:
If both match, print Yes; otherwise print No.
Why this works
First, if passes the check, then obviously the answer is Yes, because itself is a valid hidden array.
The real question is: if some valid exists, why must pass?
Assume a valid exists. Since is divisible by both and , divides .
Now look at a prefix ending at .
Because for every , we get
So the prefix GCD of is at most in the divisibility sense.
But also, for every , a real prefix GCD array must satisfy , since GCDs can only lose factors as the prefix grows. And is a multiple of , so is also a multiple of .
That means every in the prefix is divisible by , so
Together:
so they are equal.
The suffix proof is the exact same thing flipped around. For every , a real suffix GCD array satisfies , and is a multiple of , hence also a multiple of . Combined with , the suffix GCD of must equal .
So if any solution exists, the lcm candidate works. No guessing, no backtracking, no weird constructive gymnastics.
Overflow note
, so their LCM can be up to . Use long long, and compute
This stays within signed 64-bit here because the worst case is about , below .
Complexity
Each test case is linear:
because every GCD costs logarithmic time. The total over all tests is , so this is comfortably fast.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<ll> p(n), s(n), b(n);
for (ll &x : p) cin >> x;
for (ll &x : s) cin >> x;
for (int i = 0; i < n; i++) {
ll g = gcd(p[i], s[i]);
b[i] = p[i] / g * s[i];
}
bool ok = true;
ll cur = 0;
for (int i = 0; i < n; i++) {
cur = gcd(cur, b[i]);
if (cur != p[i]) ok = false;
}
cur = 0;
for (int i = n - 1; i >= 0; i--) {
cur = gcd(cur, b[i]);
if (cur != s[i]) ok = false;
}
cout << (ok ? "Yes" : "No") << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<ll> p(n), s(n), b(n);
for (ll &x : p) cin >> x;
for (ll &x : s) cin >> x;
for (int i = 0; i < n; i++) {
ll g = gcd(p[i], s[i]);
b[i] = p[i] / g * s[i];
}
bool ok = true;
ll cur = 0;
for (int i = 0; i < n; i++) {
cur = gcd(cur, b[i]);
if (cur != p[i]) ok = false;
}
cur = 0;
for (int i = n - 1; i >= 0; i--) {
cur = gcd(cur, b[i]);
if (cur != s[i]) ok = false;
}
cout << (ok ? "Yes" : "No") << '\n';
}
}