传送门
Solution
设有雪顶和无雪顶的山的总高度差为 c。
通过计算代表山峰类型的 01 矩阵的二维前缀和,可以求出每个大小为 k×k 的方形区域中,两种类型的山的数量差。设每个方形的数量差分别为 ai,则问题转换为方程
∑aixi=c
是否有整数解。xi 表示对在 ai 所在的方形内所有的山削减(或增加)多少高度。为方便计算,不妨对所有 ai 及 c 取绝对值,不影响做法正确性。
此时方程符合多元线性丢番图方程的形式。根据定理,方程有解当且仅当
gcd(a1,a2,⋅⋅⋅,an)∣c
定理证明可参考《初等数论及其应用》 ([美] Kenneth H·Rosen) 第 103 页定理 3.24 的证明,此处略。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll N = 1005;
ll T, n, m, k, a[N][N], sum[N][N], tot, ans, b[N][N]; char str[N];
void solve() { tot = ans = 0; scanf("%lld%lld%lld", &n, &m, &k); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%lld", &a[i][j]); sum[i][j] = 0; } for (int i = 1; i <= n; i++) { scanf("%s", str + 1); for (int j = 1; j <= m; j++) { a[i][j] *= (str[j] == '0' ? -1 : 1); b[i][j] = (str[j] == '0' ? -1 : 1); tot += a[i][j]; } } tot = abs(tot); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { sum[i][j] = sum[i][j - 1] + b[i][j]; if (j > k) sum[i][j] -= b[i][j - k]; } } for (int j = 1; j <= m; j++) { for (int i = 1; i <= n; i++) sum[i][j] += sum[i - 1][j]; for (int i = n; i > k; i--) sum[i][j] -= sum[i - k][j]; } for (int i = k; i <= n; i++) for (int j = k; j <= m; j++) if (sum[i][j]) ans = sum[i][j]; if (ans == 0) { if (tot == 0) printf("YES\n"); else printf("NO\n"); return; } for (int i = k; i <= n; i++) for (int j = k; j <= m; j++) if (sum[i][j]) ans = __gcd(ans, abs(sum[i][j])); if (tot % ans == 0) printf("YES\n"); else printf("NO\n"); }
int main() { scanf("%lld", &T); while (T--) solve(); return 0; }
|