傳送門
思路
吐槽
吐槽:話說不應該是他倆都得死嘛qwq
咋做
一道不好題.
我們用來表示:走到第行第列魔液差距值爲且當前爲走的方案數(表示目前爲小走,表示目前爲走)
初始條件:表示小從每個點開始取,差距值爲的方案數爲
那麼我們可以想出轉移方程:
這個式子表示目前在第行第列,差距值爲,當前小走的方案數,因爲只能往右走或往下走,且上一步一定是走的,所以可以從第行第列、第行第列轉移過來,差距值增大
同理,這個式子表示目前在第行第列,差距值爲,當前走的方案數,上一步一定是小走的,所以可以從第行第列、第行第列轉移過來,差距值減小
我們容易想出,最後的答案就是最後一維是是因爲最後一步只能由走
空間複雜度剛好可以,時間複雜度可以過
注意!
- 因爲魔液值到達之後就會清,所以在過程中要隨時對取模
- 空間開好!!不要開太大!因爲最後一維只用,所以開的數組就好了就行了,開會
- 碼風醜陋,謹慎閱讀
代碼
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int B = 20;
const int A = 800 + 7;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar(); int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int n, m, k, a[A][A], f[A][A][B][2];
int main() {
n = read(), m = read(), k = read() + 1;
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) a[i][j] = read(), f[i][j][a[i][j] % k][0] = 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
for(int p = 0; p <= k; p++) {
f[i][j][p][0] = (f[i][j][p][0] + f[i - 1][j][(p - a[i][j] + k) % k][1] + f[i][j - 1][(p - a[i][j] + k) % k][1]) % mod;
f[i][j][p][1] = (f[i][j][p][1] + f[i - 1][j][(p + a[i][j] + k) % k][0] + f[i][j - 1][(p + a[i][j] + k) % k][0]) % mod;
}
int ans = 0;
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) ans += f[i][j][0][1], ans %= mod;
cout << ans << '\n';
return 0;
}