0
点赞
收藏
分享

微信扫一扫

AcWing none. 十一届蓝桥杯7月B组——E矩阵

alanwhy 2022-02-04 阅读 29

问题描述

把 1 ∼ 2020 放在 2 × 1010 的矩阵里。

要求同一行中右边的比左边大,同一列中下边的比上边的大。一共有多少种方案?

答案很大,你只需要给出方案数除以 2020 的余数即可。

答案提交

这是一道结果填空题,你只需要算出结果后提交即可。
本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

分析

由题意我们大概可以简要得到下图的信息。

在这里插入图片描述

A < C < D , A < B < D A<C<D, A<B<D A<C<DA<B<D

从上图示意中,我们可以发现A一定是最小的数。而与A相邻的B和C一定是仅小于A的两个数。例如:若A=1,那么D绝对不可能等于2

因此,对于每个数的放法,一定是从最左边开始的。

对于一个新放的数:

  • 要么紧挨着放在上边一行
  • 要么紧挨着放在下边一行

且对于第二种情况必然是建立在上边一行已经放置的情况之下。

这种后一个的放法,仅受前一个放法影响的问题,显然具备无后效性,可以用DP的思想思考它。

在这里插入图片描述

上述的 f[i][j] 表示第一行有 i 个数,第二行有 j 个数放法。

当我们要放一个数的时,合理放法(即: i - 1 ≥ j):

  • 若放第一行,那放法数就有f[ i-1 ][ j ]
  • 若放第二行,那放法数就有f[ i ][ j-1 ]

若出现以下情况 ( 即: i - 1 < j):

在这里插入图片描述

因为它是不合法的,所以方案数 f[i][j] = f[i][j-1]

f [ i ] [ j ] = { f [ i − 1 ] [ j ] + f [ i ] [ j − 1 ] , i − 1 ≥ j f [ i ] [ j − 1 ] , i − 1 < j f[i][j]= \begin{cases} f[i-1][j]+f[i][j-1],i-1≥j \\ f[i][j-1],i-1<j \end{cases} f[i][j]={f[i1][j]+f[i][j1]i1jf[i][j1]i1<j

代码

#include <bits/stdc++.h>

using namespace std;

int dp[1011][1011];

int main()
{
    dp[0][0] = 1; //两行一个数字都不放,也是一种方案
    for (int i = 0; i <= 1010; i ++)
        for (int j = 0; j <= 1010; j ++)
        {
            if(i - 1 >= j) //转移前的状态也要合法,即第一行的数量不小于第二行的数量
                dp[i][j] += dp[i - 1][j] % 2020;
            if(j)
                dp[i][j] += dp[i][j - 1] % 2020;
        }
    cout << dp[1010][1010] << endl;
    return 0;
}

这题其实是经典例题Acwing 271.杨老师的照相排列的简化版。

举报

相关推荐

0 条评论