由于几天在洛谷颓废只打卡不做题的行为 我的洛谷账号成功掉到了绿名…
所以这几天发点洛谷上的题 先搞个动归练练手
题面
用
d
p
[
i
]
[
j
]
[
k
]
[
0
/
1
]
dp[i][j][k][0/1]
dp[i][j][k][0/1]表示当前走到了
i
i
i行
j
j
j列时二人魔液数 ?? 相差
k
k
k个时 该轮到小A/小uim拿的方案数
有点长…其实就是
i
j
i\,\,j
ij表示走到了哪
k
k
k表示二人魔液数差多少 0是小A拿 1是小uim拿
很容易可以看出
d
p
dp
dp式:
d
p
[
i
]
[
j
]
[
l
]
[
0
]
+
=
d
p
[
i
−
1
]
[
j
]
[
(
l
−
s
q
r
[
i
]
[
j
]
+
k
)
%
k
]
[
1
]
;
dp[i][j][l][0]+=dp[i-1][j][(l-sqr[i][j]+k)\%k][1];
dp[i][j][l][0]+=dp[i−1][j][(l−sqr[i][j]+k)%k][1];
d
p
[
i
]
[
j
]
[
l
]
[
0
]
+
=
d
p
[
i
]
[
j
−
1
]
[
(
l
−
s
q
r
[
i
]
[
j
]
+
k
)
%
k
]
[
1
]
;
dp[i][j][l][0]+=dp[i][j-1][(l-sqr[i][j]+k)\%k][1];
dp[i][j][l][0]+=dp[i][j−1][(l−sqr[i][j]+k)%k][1];
d
p
[
i
]
[
j
]
[
l
]
[
1
]
+
=
d
p
[
i
−
1
]
[
j
]
[
(
l
+
s
q
r
[
i
]
[
j
]
+
k
)
%
k
]
[
0
]
;
dp[i][j][l][1]+=dp[i-1][j][(l+sqr[i][j]+k)\%k][0];
dp[i][j][l][1]+=dp[i−1][j][(l+sqr[i][j]+k)%k][0];
d
p
[
i
]
[
j
]
[
l
]
[
1
]
+
=
d
p
[
i
]
[
j
−
1
]
[
(
l
+
s
q
r
[
i
]
[
j
]
+
k
)
%
k
]
[
0
]
;
dp[i][j][l][1]+=dp[i][j-1][(l+sqr[i][j]+k)\%k][0];
dp[i][j][l][1]+=dp[i][j−1][(l+sqr[i][j]+k)%k][0];
不多bb浪费篇幅 直接上代码
#include<bits/stdc++.h>
using namespace std;
#define reg register
const int mod=1e9+7;
inline void read(int &x){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
int n,m,k,ans,dp[801][801][16][2],sqr[801][801];
int main(){
read(n),read(m),read(k);k++;
for(reg int i=1;i<=n;i++){
for(reg int j=1;j<=m;j++){
read(sqr[i][j]);
sqr[i][j]%=k;
dp[i][j][sqr[i][j]][0]=1;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int l=0;l<k;l++){
if(i>1)(dp[i][j][l][0]+=dp[i-1][j][(l-sqr[i][j]+k)%k][1])%=mod;
if(j>1)(dp[i][j][l][0]+=dp[i][j-1][(l-sqr[i][j]+k)%k][1])%=mod;
if(i>1)(dp[i][j][l][1]+=dp[i-1][j][(l+sqr[i][j]+k)%k][0])%=mod;
if(j>1)(dp[i][j][l][1]+=dp[i][j-1][(l+sqr[i][j]+k)%k][0])%=mod;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
(ans+=dp[i][j][0][1])%=mod;
}
}
printf("%d\n",ans);
}