【题意】
Nikita 喜欢爬山。当地的山可以看作一个由 ( n × m ) (n \times m) (n×m) 个格子组成的 n × m n \times m n×m 的矩形,每一个格子都有一个初始非负高度 a i , j a_{i,j} ai,j。
格子有两种类型:
- 有雪
- 无雪
Nikita 有一种超能力:他可以任意选择一个 k × k k \times k k×k 的子矩形,使这个子矩形中的所有格子的高度增加同一个常量 c c c( c c c 可以自己指定,每次操作未必相同)。 c c c 可以是负数。
Nikita 希望通过有限次操作使得有雪的格子的总高度和无雪的格子的总高度相等。
你的任务是判断是否可行。
【读入】
本题有多组数据。
第一行一个整数 t ( 1 ≤ t ≤ 1 × 1 0 4 ) t(1 \leq t \leq 1 \times 10^{4}) t(1≤t≤1×104),表示一共有 t t t 组数据。
每组数据的第一行三个整数 n , m , k ( 1 ≤ n , m ≤ 500 , 1 ≤ k ≤ min { n , m } ) n,m,k(1 \leq n,m \leq 500, 1\leq k \leq \min \left \{ n,m \right \}) n,m,k(1≤n,m≤500,1≤k≤min{n,m})。
接下来 n n n 行,每行 m m m 个整数,表示初始高度 a i , j ( 0 ≤ a i , j ≤ 1 × 1 0 9 ) a_{i,j}(0 \leq a_{i,j} \leq 1 \times 10^{9}) ai,j(0≤ai,j≤1×109)。
接下来 n n n 行,每行一个长度为 m m m 的有 0 , 1 0,1 0,1 构成的字符串(没有空格), 0 0 0 表示该格子无雪, 1 1 1 表示有雪。
保证所有数据的 n × m n \times m n×m 总和不超过 250 , 000 250,000 250,000。
【输出】
t t t 行,表示答案。如果 Nikita 可以在有限次操作后达成目标,则输出 Yes
,否则输出 No
。
不区分大小写,如 YES
,Yes
,yEs
都表示给出肯定答案。
Translated by HPXXZYY.
[Solution] \color{blue}{\texttt{[Solution]}} [Solution]
显然,每个格子的值具体是多少我们并不关心,我们只关心两种格子的值的差值,记为 Δ \Delta Δ。
很显然,对 k × k k \times k k×k 的子矩形中的每一个数都加上 c 1 c_{1} c1,再加上 c 2 c_{2} c2,与直接加上 c = c 1 + c 2 c=c_{1}+c_{2} c=c1+c2 没有区别。因此,如果有解,一定存在这样的解:我们对每个需要变化的子矩形最多进行 1 1 1 次操作。
当然,如果对某个子矩形不进行操作,我们也可以对它进行一次加上 c = 0 c=0 c=0 的操作。这样,一定存在这样的一组解:我们对每个 k × k k \times k k×k 的子矩形都进行且只进行 1 1 1 次操作。
对于某个子矩形,加入它有 x x x 个有雪的格子,那么它一定有 ( k 2 − x ) \left ( k^{2}-x \right ) (k2−x) 个没有雪的格子。那么对这个子矩形进行一次操作后,会使 Δ \Delta Δ 变化为 Δ + c × [ ( k 2 − x ) − x ] \Delta + c \times \left [ \left ( k^{2}-x \right ) -x\right ] Δ+c×[(k2−x)−x](显然你想要 Δ \Delta Δ 减小只需让 c c c 为负数)。
对每个子矩形维护这样一个特征值 [ ( k 2 − x ) − x ] \left [ \left ( k^{2}-x \right ) -x\right ] [(k2−x)−x],记为 t t t。对这个子矩形的操作必然使 Δ \Delta Δ 增加或减小 t t t 的倍数。
这样我们就获得了一系列的 t t t,记为 t 1 , t 2 , t 3 , … , t g t_{1},t_{2},t_{3}, \dots ,t_{g} t1,t2,t3,…,tg。问题变成解下面的不定方程是否有整数解:
Δ = ∑ i = 1 g c i ⋅ t i \Delta=\sum\limits_{i=1}^{g}c_{i} \cdot t_{i} Δ=i=1∑gci⋅ti
显然如果 Δ \Delta Δ 是 gcd { t i } \gcd \{ t_{i} \} gcd{ti} 的倍数,则有解;反之则无解。
[code] \color{blue}{\text{[code]}} [code]
typedef long long ll;char c[510];
int n,m,T,res,k;ll delta;
int a[510][510],b[510][510],s[510][510];inline int Abs(int u){return ((u<0)?-u:u);
}
inline int gcd(int u,int v){if (v==0) return u;return gcd(v,u%v);
}int main(){T=read();while (T--){n=read();m=read();k=read();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=read();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[i][j]=s[i][j]=0;//只能这么清空 delta=0;res=-1;for(int i=1;i<=n;i++){scanf("%s",c+1);for(int j=1;j<=m;j++)if (c[j]=='1'){delta+=a[i][j];b[i][j]=1;}else{delta-=a[i][j];b[i][j]=-1;}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+b[i][j];for(int i=k;i<=n;i++)for(int j=k;j<=m;j++){int tmp=s[i][j]-s[i-k][j]-s[i][j-k]+s[i-k][j-k];if (res==-1) res=Abs(tmp);else res=gcd(res,Abs(tmp));}if (res==0) printf("%s\n",(delta==0?"Yes":"NO"));else if (delta%res==0) printf("yEs\n");else printf("nO\n");}return 0;
}