原题链接
只要想好状态,这题就是水题了,转移方程完全没难度。。
设(f[i][j][w][u])表示走到((i, j))格,小(a)和(uim)所取得魔力值的差值为(w),该格由((u = 0)则小(a)取,(u = 1)则(uim)取)时的总方案数。
设格子((i, j))的魔力值为(a[i][j]),则有状态转移方程:
(qquadqquad f[i][j][w][0] = f[i][j][w][0] + f[i - 1][j][v][1] + f[i][j - 1][v][1],quad v = (w - a[i][j] + k + 1) \% (k + 1))
(qquadqquad f[i][j][w][1] = f[i][j][w][1] + f[i - 1][j][v][0] + f[i][j - 1][v][0],quad v = (w + a[i][j]) \% (k + 1))
因为小(a)能从任意一个格子开始走,所以初值为(i = 1 o n, j = 1 o m, f[i][j][a[i][j]][0] = 1)。
最后答案为(sumlimits_{i = 1}^nsumlimits_{j = 1}^m f[i][j][0][1])
#include<cstdio>
using namespace std;
const int N = 810;
const int M = 16;
const int mod = 1e9 + 7;
int f[N][N][M][2], a[N][N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline long long MOD(long long x)
{
if (x < mod)
return x;
return x - mod;
}
int main()
{
int i, j, n, m, k, o, w, v, s = 0;
n = re();
m = re();
k = re();
o = k + 1;
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
{
a[i][j] = re();
f[i][j][a[i][j]][0] = 1;
}
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
for (w = 0; w <= k; w++)
{
v = (w - a[i][j] + o) % o;
f[i][j][w][0] = MOD(MOD(1LL * f[i - 1][j][v][1] + f[i][j - 1][v][1]) + f[i][j][w][0]);
v = (w + a[i][j]) % o;
f[i][j][w][1] = MOD(MOD(1LL * f[i - 1][j][v][0] + f[i][j - 1][v][0]) + f[i][j][w][1]);
if (!w)
s = MOD(1LL * s + f[i][j][0][1]);
}
printf("%d", s);
return 0;
}