题意
牛牛可以在n*m的图中向右走或者向下走,每个点有一个权值,经过某点获得该点权值并对1e4+7求模,问从(1,1)走到(n,m),在(n,m)点存在多少种权值情况。
题解
设一个dp三维布尔数组,dp[i][j][k]表示从(1,1)走到(i,j)点是否在(i,j)点可以产生k的权值。
易知转移方程
即当前位置只能由上面一格或左面一格转移而来,且若想权值可以为k,则转移前的权值需要为
code
#include <bits/stdc++.h> #define reg register #define ll long long #define ull unsigned long long #define pii pair<int,int> #define inf 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) #define e exp(1.0) #define ios ios::sync_with_stdio(false) #define rep(i,l,r) for(int i=(l);i<(r);i++) using namespace std; const int maxn = 100 + 10; const int mod = 1e4 + 7; int n,m; int v[maxn][maxn]; bool dp[105][105][10010]; int main() { cin>>n>>m; for(int i = 1;i <= n;++i){ for(int j = 1;j <=m;++j){ cin>>v[i][j]; v[i][j] %= mod; } } dp[1][1][v[1][1]] = 1; for(int i = 1;i <= n;++i){ for(int j = 1;j <= m;++j){ for(int k = 0;k < mod;++k){ dp[i][j][k] |= dp[i-1][j][(k-v[i][j]+mod) % mod]; dp[i][j][k] |= dp[i][j-1][(k-v[i][j]+mod) % mod]; } } } int res = 0; for(int i = 0;i < mod;++i) res += dp[n][m][i]; printf("%d\n",res); return 0; }