/* 显然用dp[i][j]来表示i个1,j个-1的结果 dp[i][j]由dp[i-1][j]和dp[i][j-1]转移而来 即dp[i][j]对应的所有序列,都可以由dp[i-1][j]在前面加一个1或dp[i][j-1]在前面加一个-1得到, 这里加在前面是因为更容易统计 考虑1加在前面,那么对于任意一种(i-1,j)的排列,贡献都+1,C(i-1+j,j) 考虑-1加在前面,那么对于某些(i,j-1)的排列,贡献-1 考虑哪些不需要,前缀中-1的个数始终大于1的序列本来答案就是0,因此不需要-1 预处理这样的序列个数 f[i][j]表示有i个1,j个-1时,前缀-1数量大于1的序列个数 f[i][j]的来源有两种f[i][j-1],f[i-1][j] 对于f[i][j]的每种序列,都可以由 f[i][j-1] 后加一个-1,或者 f[i-1][j]后面加一个1得到 初始值:f[o][j]=1,f[i][j]=0,i>j */
#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/zsben991126/p/11517365.html
时间: 2024-10-10 13:27:20