• 【LOJ3600】「PA 2021」Od deski do deski(DP)


    题目链接

    • 求有多少个长度为 \(n\) 、值域为 \(1\sim m\) 的序列,满足可以通过若干次删除长度大于 \(1\) 且两端元素相同的区间将其删空。
    • \(1\le n\le3\times10^3\)\(1\le m\le10^9\)

    判断合法的条件

    考虑如何判断一个序列是否合法。

    从左往右扫一遍,维护所有合法的端点值,初始只有第一个数的值。

    如果一个位置填了合法的值,则后一个位置的值在填写后也将变成合法的。

    只要满足最后一个数填写时是合法的值即可。

    动态规划

    发现合法的值具体是谁并没有影响,因此只需记录合法的值的个数。

    \(f_{i,j}\) 表示填到第 \(i\) 个数一共有 \(j\) 个合法值,且 \(i\) 填写时不是合法值的方案数;\(g_{i,j}\) 表示 \(i\) 填写时是合法值的方案数。

    转移比较简单,填了合法值会转移到 \(g\),填了不合法值会转移到 \(f\),且从 \(g\) 转移到 \(f\) 时合法值个数会加 \(1\)

    代码:\(O(n^2)\)

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Rg register
    #define RI Rg int
    #define Cn const
    #define CI Cn int&
    #define I inline
    #define W while
    #define N 3000
    #define X 1000000007
    using namespace std;
    int n,m,f[N+5][N+5],g[N+5][N+5];
    int main()
    {
    	RI i,j;for(scanf("%d%d",&n,&m),f[1][1]=m,i=2;i<=n;++i) for(j=1;j<=min(i,m);++j)
    		f[i][j]=(1LL*f[i-1][j]*(m-j)+1LL*g[i-1][j-1]*(m-j+1))%X,g[i][j]=1LL*(f[i-1][j]+g[i-1][j])*j%X;//DP转移
    	RI t=0;for(j=1;j<=min(n,m);++j) t=(t+g[n][j])%X;return printf("%d\n",t),0;
    }
    
  • 相关阅读:
    golang image库的使用
    http1.0/1.1/2.0/h2c/golang使用随笔
    3、逻辑回归 && 正则化
    1、Batch Normalization
    5、极大似然估计
    4、交叉熵与softmax
    2、卷积核,感受野
    Vue学习
    Qeios、github、overleaf、paperwithcode, 越来越多的web云端工具
    投稿遇到的arxiv论文引用问题的办法
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ3600.html
Copyright © 2020-2023  润新知