CF1204E (dp+数学)

时间:2019-08-21
本文章向大家介绍CF1204E (dp+数学),主要包括CF1204E (dp+数学)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

比赛的时候一直在想枚举一个最大值然后算有多少个排列的最大值为枚举的值
并且膜数还看错了
于是GG


我现在才知道可以一起考虑的……还是菜……
考虑\(dp[i][j]\)表示有\(i\)\(1\)\(j\)\(-1\)时的答案
显然它可以从\(dp[i-1][j]\)\(dp[i][j-1]\)转移过来

\(dp[i-1][j]\)表示的序列开头加一个\(1\),最大前缀和也会+1。而这样的序列一共有\(C^{i+j-1}_j\)种,所以\(dp[i-1][j]\)\(dp[i][j]\)的贡献为\(C^{i+j-1}_j\)

同理,在\(dp[i][j-1]\)表示的序列开头加一个\(-1\),最大前缀和也会\(-1\)……貌似并不是,只有最大前缀和\(>0\)时才有得减

考虑算最大前缀和\(=0\)的方案数,设\(k[i][j]\)表示有\(i\)\(1\)\(j\)\(-1\)时,最大前缀和为0的方案数。当\(i>j\)时,\(k[i][j]=0\),当\(i=0\)时有\(k[i][j]=1\)。其他情况有\(k[i][j]=k[i-1][j]+k[i][j-1]\),因为\(i-1< j\),所以在末尾加一个\(1\),最大前缀和不变。

代码:

#include <bits/stdc++.h>
#define N 2010
#define mod 998244853
#define For(i,x,y) for(int i=(x);i<=(y);++i)
#define Rof(i,x,y) for(int i=(x);i>=(y);--i)
using namespace std;

int C[N<<1][N<<1],dp[N][N],k[N][N];

inline int add(int x,int y){ return x+y>=mod?x+y-mod:x+y; }
inline int mns(int x,int y){ return x-y<0?x-y+mod:x-y; }
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    For(i,0,n+m){ 
        C[i][0]=1;
        For(j,1,i) C[i][j]=add(C[i-1][j],C[i-1][j-1]);
    }   
    For(i,1,m) k[0][i]=1;
    For(i,1,n) For(j,i,m) k[i][j]=add(k[i-1][j],k[i][j-1]);
    For(i,1,n) dp[i][0]=i;
    For(i,1,n)
        For(j,1,m)
            dp[i][j]=add(add(dp[i-1][j],C[i+j-1][j]),mns(dp[i][j-1],mns(C[i+j-1][i],k[i][j-1])));
    cout<<dp[n][m];
}

原文地址:https://www.cnblogs.com/PsychicBoom/p/11391572.html