转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
给定一个序列,a[1 。。k],问是否存在(i , j)使得 GCD(i , j + r - 1) = a[r] (k>=r >=1),其中 i <= n && j + k - 1 <= m
http://codeforces.com/contest/338/problem/D
首先容易知道row = lcm (a[1……k]),是最小可能存在解的行。
官方题解中有证明,反正乱七八糟的。。。我太弱了,看不懂
之后我们找到最小的col满足
col % a[1] = 0
(col + 1) % a[2] = 0
……
(col + k - 1) % a[k] = 0
这个东西用CRT求出来。
最后check一下row , col是否满足,就结束了。。。
显然j < col 是不可能满足的,而且col + x * row肯定也是可能满足的。
当然可能存在gcd (col + r - 1 , row) > a[r]。
所以col缩小是肯定不满足的,而即使你增大col若干倍,只可能使得偏差更大。
接下来就注意一下各种细节,比如溢出等问题
#include <iostream> #include <queue> #include <algorithm> #include <cstdio> #include <cstring> #define lson step << 1 #define rson step << 1 | 1 using namespace std; typedef long long LL; const int N = 10005; LL n , m , a[N] , row = 1LL; int k; LL gcd (LL a , LL b) { return b == 0 ? a : gcd (b , a % b); } LL extend_gcd (LL a , LL b , LL &x , LL &y) { if (b == 0) { x = 1LL; y = 0; return a; } LL g = extend_gcd (b , a % b , x , y); LL t = x; x = y; y = t - a / b * x; return g; } int main() { int t; #ifndef ONLINE_JUDGE freopen ("input.txt" , "r" , stdin); // freopen ("output.txt" , "w" , stdout); #endif cin >> n >> m >> k; for (int i = 0 ; i < k ; i ++) { cin >> a[i]; row = row / gcd (row , a[i]) * a[i]; if (row <= 0 || row > n) { puts ("NO"); return 0; } } // Z = u + v * x LL u = 0LL , v = a[0]; for (int i = 1 ; i < k ; i ++) { // Z = U + V * x1 // Z = - i + a[i] * x2 // v * x - a[i] * y = - u - i // A * x + B * y = C LL x , y , A = v , B = -a[i] , C = - u - i; LL g = extend_gcd (A , B , x , y); if (C % g) { puts ("NO"); return 0; } if (B % g) puts ("ERROR"); LL t = B / g; x = x * (C / g); x = (x % t + t) % t; if (x < 0) x -= t; // y = (C - A * x) / B; u = u + v * x; v = v / gcd (v , a[i]) * a[i]; } if (u == 0) u += row; if (u + k - 1 > m) { puts ("NO"); return 0; } for (int i = 0 ; i < k ; i ++) { if (gcd (row , u + i) != a[i]) { puts ("NO"); return 0; } } puts ("YES"); return 0; }