题目描述
题目链接←点我
给出一张n*m的GCD表,第i行第j列的数字大小为 gcd(i,j)即i和j的最大公因数,给出一个数字序列a1,a2,。。。,ak(1 ≤ ai ≤ 1012),1<=k<=104,问该数字序列是否在GCD表的某一行中完整出现过,答案输出YES或NO
例如:
题目给出N=4,M=8,则为一张4 * 8 的 GCD 表(如下),给出数列3 1 1 2,因为它其在GCD表中出现过,答案输出YES
1 1 1 1 1 1 1 1
1 2 1 2 1 2 1 2
1 1 3 1 1 2 1 1
1 2 1 4 1 2 1 4
题目分析
首先,假如给出的数列在GCD表中x行y列开始出现。
ai = gcd(x,y+i) (1<=i<=k),则x = k * lcm(a1,…,ak),k >=1,因为ai均为x的因子。若lcm > n,则无解.
若lcm<=n,我们可以写出如下式子
t1 * a1 = y
t2 * a2 = y + 1
. . .
tk * ak = y + (k -1)
ai = gcd(x,y+i-1)
=> x = si * ai
&& y + i - 1 = ti * ai
将上述式子转化为同余方程的形式
y = 0 mod a1
y = -1 mod a2
. . .
y = 1 - k mod ak
然后用拓展中国剩余定理解出y,若y>m-k+1则无解(数列未全部在n*m的GCD表中)
最后逐步验证 ai = gcd(x,y+i-1)是否全部成立
代码参考
/*
* @Author: CHAOS_ORDER
* @Date: 2019-08-11 14:36:48
* @LastEditors: CHAOS_ORDER
* @LastEditTime: 2019-09-03 20:55:21
* @Description: GCD Table https://codeforces.com/contest/338/problem/D
* @Status: Accepted 60ms
*/
#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define sd(i) scanf("%d", &i)
#define pd(i) printf("%d", i)
#define slld(i) scanf("%lld", &i)
#define plld(i) printf("%lld", i)
#define schstr(i) scanf("%s", i)
#define pchstr(i) printf("%s", i)
#define For(i, begin, end) for (register int i = begin; i <= end; i = i + 1)
#define rFor(i, begin, end) for (register int i = begin; i >= end; i = i - 1)
#define newline printf("\n")
#define pause system("pause")
#define mod 1000000007
#define inf 0x3f3f3f3f
typedef long long ll;
const ll maxn = 1e4 + 7;
const ll maxm = 1e7 + 7;
ll a[maxn];
ll N, M;
int k;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
ll ans = exgcd(b, a % b, y, x);
y -= x * (a / b);
return ans;
}
void excrt()
{
ll m = a[1], r = 0, x, y, g;
For(i, 2, k)
{
g = exgcd(m, a[i], x, y);
if ((1 - i - r) % g)
{
return pchstr("NO"), void();
}
ll mul = a[i] / g;
x = x * (1 - i - r) / g;
x = (x % mul + mul) % mul;
r = r + m * x;
m = m * a[i] / g;
r = (r % m + m) % m;
}
if (r == 0)
r = m;
if (r + k - 1 > M)
return pchstr("NO"), void();
For(i, 1, k)
{
if (__gcd(m, r + i - 1) != a[i])
return pchstr("NO"), void();
}
pchstr("YES");
}
bool check()
{
ll lcm = 1;
For(i, 1, k)
{
lcm = lcm / __gcd(a[i], lcm) * a[i];
if (lcm > N)
return false;
} //求x = lcm(a[1],...,a[k]), N 一定大于 x ,否则答案为“NO”
return true;
}
int main()
{
slld(N), slld(M), sd(k);
For(i, 1, k)
slld(a[i]);
if (check())
excrt();
else
pchstr("NO");
return 0;
}