dp[i][j][h][l] 表示在点 (i,j),差值为h,小A还是uim取液体的方案数(0:小A 1:uim)
转移方程:
dp[i][j][h][1]+=(dp[i-1][j][(h-a[i][j]+k)%k][0])
dp[i][j][h][1]+=(dp[i][j-1][(h-a[i][j]+k)%k][0]
dp[i][j][h][0]+=(dp[i-1][j][(h+a[i][j])%k][1])
dp[i][j][h][0]+=(dp[i][j-1][(h+a[i][j])%k][1])
初始化:dp[i][j][a[i][j]][0]=1; 一开始小A可以从任意点开始
我一开始一直在纠结A吸毒液和B吸毒液的区别 一直想不通为什么一个是+a[i][j],一个是-a[i][j],其实很简单,因为两个人是A取一次 B再取一次的 A吸毒液 相当于给整体的差值加了k B吸毒液 相当于给整体的差值减了k
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 805
#define mod 1000000007
using namespace std;
int n,m,K,a[N][N],dp[N][N][18][2]; //0:小A 1:uim
typedef long long ll;
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
cin>>n>>m>>K;
K++;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
dp[i][j][a[i][j]][0]=1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=0;k<=K-1;k++)
{
dp[i][j][k][0]=(dp[i][j][k][0]+dp[i-1][j][(k-a[i][j]+K)%K][1])%mod;
dp[i][j][k][0]=(dp[i][j][k][0]+dp[i][j-1][(k-a[i][j]+K)%K][1])%mod;
dp[i][j][k][1]=(dp[i][j][k][1]+dp[i-1][j][(k+a[i][j])%K][0])%mod;
dp[i][j][k][1]=(dp[i][j][k][1]+dp[i][j-1][(k+a[i][j])%K][0])%mod;
}
}
}
ll ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
ans=(ans+ll(dp[i][j][0][1]))%mod;
}
cout<<ans<<endl;
return 0;
}