题解:CF2232E Snaking Arrangement
我说这题真挺牛的。
有一个比较显然的观察是他应该是一个对称的图形。我们只用看左上部分即可。至于为什么得等后面再证。
这样的话我们就相当于要在一个上三角里塞长度为
这启发我们把矩阵转四十五度,然后斜着一行行考虑。
你发现一个很优秀的性质,如果上一行已经确定了,那么此时如果我们确定这一行的蛇头,方案是唯一的。比如这是我们原来的方案:
此时我们钦定下一行的蛇头(蓝色的位置),那么方案一定只能是:
并且,所有在这个新蛇头“左边”的位置会向原矩阵下走,在新蛇头“右边”的位置会向右走。
那其实你发现这个关系应该是对应的。换句话说,我们强制原来一条蛇向右走,这一行对应的蛇头就应该在这条蛇的“左边”,反之同理。
因此,转置矩阵的一行上,只有一个区间能够放蛇头。
然后你直接乘法原理即可。
AC Code
#include<bits/stdc++.h>
#define int long long
using namespace std ;
const int MAXN = 1e4 + 7 ;
const int MOD = 1e9 + 7 ;
int L[MAXN] , R[MAXN] ;
char p[MAXN] ;
void solve() {
int n , k ;
cin >> n >> k ;
for (int i = 1 ; i <= n ; i ++) {
L[i] = 1 ;
R[i] = i ;
}
for (int i = 1 ; i <= k ; i ++) {
int s ;
cin >> s ;
int r , c ;
cin >> r >> c ;
if (s > 1) cin >> p ;
int g = r + c - 1 ;
if (L[g] > r or R[g] < r) {
cout << 0 << "\n" ;
return ;
}
L[g] = R[g] = r ;
g ++ ;
for (int j = 0 ; j < s / 2 ; j ++ , g ++) {
if (p[j] == 'R') {
L[g] = max(L[g] , r + 1) ;
c ++ ;
}
else {
R[g] = min(R[g] , r) ;
r ++ ;
}
if (L[g] > R[g]) {
cout << 0 << "\n" ;
return ;
}
}
}
int ans = 1 ;
for (int i = 1 ; i <= n ; i ++) {
ans = ans * (R[i] - L[i] + 1) % MOD ;
}
cout << ans << "\n" ;
}
signed main() {
ios::sync_with_stdio(0) ;
cin.tie(0) ;
cout.tie(0) ;
int t ;
cin >> t ;
while (t--) {
solve() ;
}
return 0 ;
}