题目大意
有 n n n 个数,定义 i , j ( i < j ) i,\space j(i
解题思路
原来的数列全为 0 0 0 则不用操作,此外,如果 k > n 2 k>\frac{n}{2} k>2n 则无法操作
在剩余情况中,可以把每 k k k 个数取出来形成新环(可能不止一个环),在新环上就是相邻的数操作了
设新的数列为 { b i } \{b_i\} {bi},设 b 1 , b 2 b_1,\space b_2 b1, b2 减了 x 1 x_1 x1, b 2 , b 3 b_2,\space b_3 b2, b3 减了 x 2 x_2 x2… b m − 1 , b m b_{m-1},\space b_m bm−1, bm 减了 x m − 1 x_{m-1} xm−1, b m , b 1 b_m,\space b_1 bm, b1 减了 x m x_m xm
所以 b 1 = x m + x 1 , b 2 = x 1 + x 2 , b 3 = x 2 + x 3 b_1=x_m+x_1,\space b_2=x_1+x_2,\space b_3=x_2+x_3 b1=xm+x1, b2=x1+x2, b3=x2+x3… b m = x m − 1 + x m b_m=x_{m-1}+x_m bm=xm−1+xm
这样就可以用 x 1 x_1 x1 和 b i b_i bi 表示所有 x i x_i xi,根据 x i ≥ 0 x_i\ge0 xi≥0 求出是否有 x 1 x_1 x1 满足条件即可
注意思考一些特殊条件即可
code
#include
using namespace std;
const int N = 1e6 + 9;
int t, n, k, v[N], num, q[N], fl;
long long a[N], ma;
int main() {
scanf("%d", &t);
while (t --) {
scanf("%d%d", &n, &k); ma = fl = 0;
for (int i = 0; i < n; ++ i)
scanf("%lld", &a[i]), ma = max(a[i], ma);
if (ma == 0) {printf("YES\n"); continue;}
if (k > n / 2) {printf("NO\n"); continue;}
for (int i = 0; i < n; ++ i) v[i] = 0;
for (int i = 0; i < n; ++ i) {
if (v[i]) continue;
num = 0; q[++ num] = i; v[i] = 1;
for (int j = (i + k) % n; j != i; j = (j + k) % n)
q[++ num] = j, v[j] = 1;
long long cnt = 0, tmp = 1, l = 0, r = 1e9;
for (int j = 2; j <= num; ++ j) {
cnt = -cnt; tmp = -tmp; cnt += a[q[j]];
if (tmp == 1) l = max(l, -cnt);
else r = min(r, cnt);
}
if (tmp == 1) {
if ((a[q[1]] - cnt) % 2 != 0) {fl = 1; break;}
long long ans = (a[q[1]] - cnt) / 2;
if (ans < l || ans > r || l > r) {fl = 1; break;}
} else if (cnt != a[q[1]] || l > r) {fl = 1; break;}
}
if (fl) printf("NO\n");
else printf("YES\n");
}
return 0;
}