传送门ios
思路:c++
从k = 2 * x - y ==> 2 * x = k + y ,能够看出x是k,y的中间值,则若是存在x1,x2,且x1 = x2 ± 1,则经过x1,x2获得全部整数,则任意的k都成立。数组
例如:2 3 ===> 2 3 4 ===> 1 2 3 4 ...... spa
对于该数组A: (0 6 9 12 20),咱们能够获得a[i] - a[i - 1]的数组(6,3,3,8)。3d
能够获得A对于元素能够表示一个集合:code
a[1] -> a[1] + 6 * nblog
a[2] -> a[2] + 3 * nci
a[3] -> a[3] + 3 * nget
a[4] -> a[4] + 8 * nit
而咱们只须要确认,这些集合合并以后是否存在x1,x2且x1 = x2 ± 1.咱们任取两个集合 a(x) + p * n , a(y) + q * m(n,m ∈ Z),
则须要存在
a(x) - p * n - ( a(y) + q * m ) = 1
==> q * m - p * n = 1 * (1 - a(x) + a(y)) 有解,假设右边为T,则gcd(p, m) | T,若是a[i] - a[i-1]数组中存在两个差值的gcd = 1,则必定有解。咱们只需求
gcd(a[i - 1] - a[i], a[i - 2] - a[i - 1]....) = GCD判断是否是1便可,若是为1,则能够说明全部A集合合并后能够表示为 a[1] + n (n∈Z),即必定有解;若是不为1,
全部数合并的集合也能够表示为a[1] + GCD * n (n∈Z),判断k是否是属于a[1] + GCD * n的集合的一个元素便可。
固然以上是经过样例推出,不严谨,如下给出其中一个遗漏点的证实。
假设数组:
a b c d 若是 2 * b - a = key ,则
a b c key d
咱们须要证实gcd(b - a, c - b, d - c) = gcd(b - a, c - b, 2 * b - a - c, d - (2 * b - a) ),经过gcd的两个性质:
①gcd(a, b, c) = gcd(a, gcd(b, c))
②gcd(a, b) = gcd(a, b - a) = gcd(a, b + a)
假设gcd(b - a, c - b, 2 * b - a - c, d - (2 * b - a) ) = T,
T = gcd(b - a, c - b, gcd(2 * b - a - c, d - (2 * b - a) ) )
经过 d - (2 * b - a) + (2 * b - a - c) = d - c,
T = gcd(..., gcd(2 * b - a - c, d - c))
T = gcd(b - a, d - c, gcd(c - b, 2 * b - a - c) )
经过 2 * b - a - c - (c - b) = b - a
T = gcd(b - a , c - b, c - d),因此左边=右边。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 #define ll long long 5 6 const int N = 3e5 + 10; 7 ll a[N]; 8 9 void solve() 10 { 11 int T; 12 cin >> T; 13 while(T--) { 14 int n; 15 ll k; 16 cin >> n >> k; 17 for(int i = 1; i <= n; ++i) cin >> a[i]; 18 ll gcd = 0; 19 for(int i = 2; i <= n; ++i) { 20 gcd = __gcd(gcd, a[i] - a[i - 1]); 21 } 22 if(abs(a[1] - k) % gcd) cout << "NO" << endl; 23 else cout << "YES" << endl; 24 } 25 } 26 27 int main(){ 28 29 ios::sync_with_stdio(false); 30 cin.tie(0); cout.tie(0); 31 solve(); 32 33 return 0; 34 }