题意
给你一个 的表
,
行
列的元素为
,然后给你一个序列
,让你在表格里面找一个行的连续元素,满足
,
,
思路
这边的序列变成 ,
因为,可以推导出
设等于
很显然第一个的通解为,
第二的通解,我们设为
那么可能的解为,
这样枚举判断所有解是否合法的话肯定是不行的,
我们假设是解,
那么可以得到 ,
根据方程可以知道 ,
又因为 (因为
肯定是
和
的因子)
那么可以知道 ,因为
也等于
,所以
,
其它也可以用相同的方法证明
所以可以知道其他解成立的情况下,第一个解也一定成立,所以我们只需要判断第一个解就好
代码
#include <bits/stdc++.h>
using namespace std;
#define dd(x) cout << #x << " = " << x << ' '
#define de(x) cout << #x << " = " << x << '\n'
typedef long long ll;
typedef pair<ll, ll> pll;
ll exgcd(ll a, ll b, ll& x, ll& y) {
if (!b) return x = 1, y = 0, a;
ll g = exgcd(b, a % b, x, y);
tie(x, y) = make_tuple(y, x - a / b * y);
return g;
}
ll qmul(ll a, ll b, ll c) {
ll ret = 0;
while(b) {
if (b & 1) {
ret = (ret + a) % c;
}
a = (a + a) % c;
b >>= 1;
}
return ret;
}
pll get_ans(ll p1, ll r1, ll p2, ll r2) {
if (r1 < r2) {
swap(r1, r2);
swap(p1, p2);
}
ll x = -1, y = -1;
ll g = exgcd(p2, p1, y, x);
assert(g);
ll p = p1 / g * p2;
assert(p);
if ((r1 - r2) % g) return pair(0ll, 0ll);
ll d = (r1 - r2) / g;
// ll x0 = (qmul(qmul(p2, y, p), d, p) + r2) % p;
ll x0 = ((__int128) p2 * y % p * d % p + r2) % p;
if (x0 < 0) {
x0 = x0 + (-x0 + p - 1) / p * p;
} else {
x0 = x0 - x0 / p * p;
}
if (!x0) x0 = p;
return pair(p, x0);
}
int main() {
ios_base::sync_with_stdio(0);cin.tie(0);
ll n, m; cin >> n >> m;
int k; cin >> k;
vector<ll> a(k);
for (int i = 0; i < k; ++i) cin >> a[i];
if (k == 1) {
if (n >= a[0] && m >= a[0]) cout << "YES" << '\n';
else cout << "NO" << '\n';
return 0;
}
ll L = a[0];
for (int i = 1; i < k; ++i) {
ll x = -1, y = -1;
ll g = exgcd(L , a[i], x, y);
ll l = L / g;
assert(g);
ll r = a[i];
// if (l > n || r > n) return cout << "NO" << '\n', 0;
assert(l);
if (n / l < r) return cout << "NO" << '\n', 0;
L = l * r;
}
ll p = a[0], r = 0;
for (int i = 1; i < k; ++i) {
auto [pp, rr] = get_ans(p, r, a[i], ((-i) % a[i] + a[i]) % a[i]);
p = pp, r = rr;
if (!p) return cout << "NO" << '\n', 0;
}
auto check = [&] (ll L, ll j0) {
if (j0 > m - k + 1) return false;
for (int i = 0; i < k; ++i) {
ll x = -1, y = -1;
ll g = exgcd(L, j0 + i, x, y);
// dd(L), dd(j0 + i), dd(g), de(a[i]);
if (g != a[i]) return false;
}
return true;
};
// dd(L), de(r);
cout << (check(L, r) ? "YES" : "NO") << '\n';
return 0;
}