问题描述
把 1 ∼ 2020 放在 2 × 1010 的矩阵里。
要求同一行中右边的比左边大,同一列中下边的比上边的大。一共有多少种方案?
答案很大,你只需要给出方案数除以 2020 的余数即可。
答案提交
这是一道结果填空题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
解析:
先列举一个2x3的矩阵的例子开始分析
即题目更改为:
把1~6放在2x3的矩阵里有多少种方案;
1.根据题意,可以分析出最大的数字一定要放在右下角即:
x x x
x x 6
因此题目又可以简化为:
把1~5放在第一行有三个位置,第二行有两个位置的矩阵中有多少种方案即:
x x x
x x
再次分析最大数5的位置
有两种可能
可能1:
x x 5
x x
和
可能2:
x x x
x 5
这里只分析可能2(可能1 可以和2x3矩阵一样向下分析 不再赘述)
根据可能2
题目再次简化为:
把1~4放在第一行有三个位置,第二行有一个位置的矩阵中有多少种方案即:
x x x
x
再次分析最大数4的位置
有两种可能
可能一:
x x x
4
可能二:
x x 4
x
分析可能一:
根据题意 上面三个位置分配给1~3只有一种可能即为
1 2 3
4
分析可能二:
题目再次简化为:
把1~3放在第一行有两个位置,第二行有一个位置的矩阵中有多少种方案即:
x x
x
最大数3可以放在
x 3
x
和
x x
3
这两种情况都只有一种方案,加起来就可以有两种:
1 3
2
1 2
3
把1~4放在第一行有三个位置,第二行有一个位置的矩阵中有三种方案:
1 2 3
4
1 3 4
2
1 2 4
3
根据以上发现的规律就可以使用动态规划完成了
#include <stdio.h>
int dp[1011][1011];
int main()
{
int i,j;
for(i=1;i<1011;i++){
dp[i][0]=1;
}
for(i=1;i<1011;i++){
for(j=1;j<=i;j++){
if(i==j){
dp[i][j]=dp[i][j-1];
}else{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
dp[i][j]=dp[i][j]%2020;
}
}
printf("%d",dp[1010][1010]);
return 0;
}
答案:1340