题意:中文题意就是问你n*m的大矩形里面可以分成几个小矩形
思路:可以写dp,我们定义dp[i][j] 表示的时矩形右下角的坐标是(i,j)的时候可以分成的矩形数量,那么他的转移方程时
dp[i][j] = dp[i-1][j] + dp[i][j-1] + 1 - dp[i-1][j-1]
初始化:dp[i][0] =1 ,dp[0][i] = 1 , dp[0][0] = 0
解释一下dp方程,当你矩形右下角时(i,j)的时候它可以由那个状态转移过来?时从(i-1,j) 向下一个走过来的,也可以由(i,j-1)向右一格过来,然后他们都扩展了一个所以要+1,但是有(i-1,j-1) 个格子是算重复的所以要减去就好了。
还有就是数学的思路了:
就是我们一行一列的看的话,看一行,如果是1个矩形的话答案是 n 个两个矩形的时候是 (n-1) , 三个矩形的时候是(n-3)个。。最后的和就是n+n-1+....1,列的话也是一样,之后我们乘一下就好了。
上代码:
#include <bits/stdc++.h>
using namespace std;
int dp[111][111];
int rectNum(int n, int m)//dp代码
{
memset(dp,0,sizeof(dp));
dp[0][0] = 2;
int res = 0 ;
for(int i = 1 ; i <= n ; i++){
dp[i][0] = 1 ;
}
for(int i = 1 ; i <= m ;i++)
{
dp[0][i] = 1;
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
dp[i][j] = 1 + dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1];
res += dp[i][j];
}
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
cin>>n>>m;
long long ans = 0;
for(int i = 0 ; i < n ; i++)
{
for(int j =0 ; j < m ; j++)
{
ans += (n-i)*(m-j);
}
}
cout<<ans<<endl;
}
}