题目描述
给你 n , m , k , p n,m,k,p n,m,k,p。
你有一个长度为 k k k 的数列 a a a。
询问是否存在 x , y x,y x,y, 1 ≤ x ≤ n , 1 ≤ y + k − 1 ≤ m 1 \leq x \leq n, 1 \leq y + k-1\leq m 1≤x≤n,1≤y+k−1≤m,满足 ∀ 1 ≤ l ≤ k , gcd ( x , y + l − 1 ) = a l \forall 1 \leq l \leq k,\gcd(x,y+l-1)=a_l ∀1≤l≤k,gcd(x,y+l−1)=al。
若存在,输出 YES
,否则,输出 NO
。
对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 1 0 12 , 1 ≤ m ≤ 1 0 12 , 1 ≤ k ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 12 1 \leq n \leq 10^{12},1 \leq m \leq 10^{12}, 1 \leq k \leq 10^5,1 \leq a_i \leq 10^{12} 1≤n≤1012,1≤m≤1012,1≤k≤105,1≤ai≤1012。
解题思路
前置知识:exCRT
。
根据题意显然可以列出:
{
gcd
(
x
,
y
+
1
−
1
)
=
a
1
gcd
(
x
,
y
+
2
−
1
)
=
a
2
⋯
gcd
(
x
,
y
+
k
−
1
)
=
a
k
\begin{cases}\gcd(x,y+1-1)=a_1 \\ \gcd(x,y+2-1)=a_2 \\ \cdots \\ \gcd(x,y+k-1)=a_k\end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧gcd(x,y+1−1)=a1gcd(x,y+2−1)=a2⋯gcd(x,y+k−1)=ak
我们知道
gcd
(
a
,
b
)
=
c
\gcd(a,b)=c
gcd(a,b)=c,显然有:
a
=
p
1
c
,
b
=
p
2
c
,
p
1
∤
p
2
a=p_1c,b=p_2c,p_1\nmid p_2
a=p1c,b=p2c,p1∤p2,
即:
a
∣
c
,
b
∣
c
⇒
x
∣
a
i
,
y
+
i
−
1
∣
a
i
a \mid c,b \mid c \Rightarrow x \mid a_i,y + i-1 \mid a_i
a∣c,b∣c⇒x∣ai,y+i−1∣ai
即:
x ≡ 0 ( m o d a i ) x \equiv 0 \pmod{a_i} x≡0(modai)
和
y ≡ 1 − i ( m o d a i ) y \equiv 1-i \pmod{a_i} y≡1−i(modai)
整理出:
{
y
≡
(
1
−
1
)
(
m
o
d
a
1
)
y
≡
(
2
−
1
)
(
m
o
d
a
2
)
⋯
y
≡
(
k
−
1
)
(
m
o
d
a
k
)
\begin{cases}y \equiv (1-1) \pmod{a_1} \\ y \equiv (2-1) \pmod{a_2} \\ \\ \cdots \\ y \equiv (k-1) \pmod{a_k}\end{cases}
⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧y≡(1−1)(moda1)y≡(2−1)(moda2)⋯y≡(k−1)(modak)
显然
a
i
a_i
ai 之间不一定互质,所以我们直接使用拓展中国剩余定理求解即可,这样我们就可以求出一个合法的
y
y
y。
显然 x x x 可以整除所有的 a i a_i ai ,那么满足条件的最小的 x x x 显然是 lcm { a i } \text{lcm}\{a_{i}\} lcm{ai}。
求出 x , y x,y x,y 以后验证是否在范围内即可。
时间复杂度 O ( n log n ) \mathcal{O}(n \log n) O(nlogn)。
CODE
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read()
{
int f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9'){x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
const int maxn = 100010;
int n, p;
int a, b;
int Lcm = 1;
int ai[maxn], bi[maxn];
int js(int x, int mod)
{
if(x < mod) return x;
return x % mod + mod;
}
int gcd(int a, int b)
{
if(!b) return a;
return gcd(b, a % b);
}
int lcm(int a, int b)
{
return a / gcd(a, b) * b;
}
int mul(int a, int b, int mod)
{
if(b < 0) a = -a, b = -b;
int res = 0;
while(b > 0)
{
if(b & 1) res = (res + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return res;
}
int exgcd(int a, int b, int &x, int &y)
{
if(b == 0){x = 1; y = 0; return a;}
int gcd = exgcd(b, a % b, x, y);
int tp = x;
x = y; y = tp - a / b * y;
return gcd;
}
int excrt()
{
int x, y, k;
int M = bi[1], ans = ai[1];
for(int i = 2; i <= n; ++i)
{
int a = M, b = bi[i], c = (ai[i] - ans % b + b) % b;
int gcd = exgcd(a, b, x, y), bg = b / gcd;
if(c % gcd != 0) return -1;
x = mul(x, c / gcd, bg);
ans += x * M;
M *= bg;
ans = (ans % M + M) % M;
}
ans = (ans % M + M) % M;
if(ans == 0) ans = M;
return ans;
}
int phi(int x)
{
int o = x;
for(int i = 2; i * i <= x; ++i)
{
if(x % i == 0)
{
while(x % i == 0) x /= i;
o = o / i * (i - 1);
}
}
if(x > 1) o = o / x * (x - 1);
return o;
}
int qpow(int x, int y, int mod)
{
int res = 1ll;
while(y)
{
if(y & 1ll) res = js(res * x, mod);
x = js(x * x, mod);
y >>= 1ll;
}
return x;
}
int solve(int l, int r, int mod)
{
if(l == r || mod == 1) return js(l, mod);
return qpow(l, solve(l + 1, r, phi(mod)), mod);
}
signed main()
{
a = read(), b = read(), n = read(), p = read();
for(int i = 1; i <= n; ++i)
{
bi[i] = read();
ai[i] = (1 - i + bi[i]) % bi[i];
Lcm = lcm(Lcm, bi[i]);
}
if(n > b) return puts("NO"), 0;
int x = Lcm, y = excrt();
if(y == -1) return puts("NO"), 0;
for(int i = 1; i <= n; ++i)
if(gcd(x, y + i - 1) != bi[i])
return puts("NO"), 0;
if(y < 1 || x < 1 || y + n - 1 > b || x > a)
return puts("NO"), 0;
puts("YES");
return 0;
}