题意:
就是给你一个n*m的矩阵,然后从1,1走到n,m,每次可以往下或者往右,并且走过的地方把权值加上,并且%1e4+7,问你又多少种不同的方式走到n,m的时候能获得多少种权值和。
思考:
这就是状态类型的dp了,但是你看这个数据范围卡的有点极限,如果直接定义dp为走到i,j的时候并且总和为k,这种状态是否可达。复杂度会到1e8。其实有时候还是可以过的,这个就可以直接转移就行了。当然还有一种操作就是bitset,bitset就是可以表示状态,和他有的值的个数。一些表示当前点可以到达哪些点的时候可以用他,比如可达性统计这道题,当然这里用bitset还有一些操作。
代码:
int T,n,m,k;
int va[105][105];
bool dp[105][105][mod];
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>va[i][j];
va[i][j] %= mod;
}
}
dp[1][1][va[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][(va[i][j]+k)%mod] |= dp[i-1][j][k];
dp[i][j][(va[i][j]+k)%mod] |= dp[i][j-1][k];
}
}
}
int ans = 0;
for(int i=0;i<mod;i++) ans += dp[n][m][i];
cout<<ans;
return 0;
}
bitset版本
int T,n,m,k;
int va[105][105];
bitset<30000> dp[105][105];
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>va[i][j];
va[i][j] %= mod;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i==1&&j==1) dp[i][j][va[i][j]] = 1;
else if(i==1) dp[i][j] |= (dp[i][j-1]<<va[i][j]);
else if(j==1) dp[i][j] |= (dp[i-1][j]<<va[i][j]);
else
{
dp[i][j] |= (dp[i-1][j]<<va[i][j]);
dp[i][j] |= (dp[i][j-1]<<va[i][j]);
}
dp[i][j] |= dp[i][j]>>mod;
}
}
int ans = 0;
for(int i=0;i<mod;i++) ans += dp[n][m][i];
cout<<ans;
return 0;
}
总结:
多多积累经验,尝试尝试。