題目描述見鏈接 .
設 表示 個 , 個 的答案, 從後往前 放置數字進行 狀態轉移
-
放置 : 對 產生 的貢獻 .
-
放置 : 對 產生 的貢獻 .
-
初值:
其中 表示 個 , 個 所組成的序列 最大前綴和 爲 的方案數, 先考慮特殊情況,
- , .
再考慮 時, 能更新哪些狀態,
- 填 時, 若能更新 , 則說明 且 , 所以轉移條件爲 .
- 填 時, 若能更新 , 則說明 且 , 所以轉移條件爲 .
時, .
因爲 , 一定是由於取 取到 的,
而原本最大前綴和爲 , 多放置一個 , 最大前綴和仍爲 ,
因此當 時, 放置 和 放置 都可以轉移到 .
#include<bits/stdc++.h>
#define reg register
const int maxn = 4005;
const int mod = 998244853;
int N;
int M;
int inv[maxn];
int fac[maxn];
int ifac[maxn];
int F[maxn][maxn];
int g[maxn][maxn];
int C(int n, int m){ return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod; }
int main(){
scanf("%d%d", &N, &M);
inv[1] = 1; for(reg int i = 2; i < maxn; i ++) inv[i] = ((-1ll*mod/i*inv[mod%i])%mod + mod) % mod;
fac[0] = 1; for(reg int i = 1; i < maxn; i ++) fac[i] = 1ll*fac[i-1]*i%mod;
ifac[0] = 1; for(reg int i = 1; i < maxn; i ++) ifac[i] = 1ll*ifac[i-1]*inv[i] % mod;
g[0][0] = 1;
for(reg int i = 0; i <= N; i ++)
for(reg int j = i; j <= M; j ++){
if(i < j) g[i+1][j] = (g[i+1][j] + g[i][j]) % mod;
if(i <= j) g[i][j+1] = (g[i][j+1] + g[i][j]) % mod;
}
for(reg int i = 1; i <= N; i ++) F[i][0] = i;
for(reg int i = 0; i <= N; i ++)
for(reg int j = 1; j <= M; j ++){
int add = (F[i][j-1] - ((C(i-1+j, j-1)-g[i][j-1])%mod+mod)%mod + mod) % mod;
F[i][j] = (F[i][j] + add) % mod;
if(!i) continue ;
add = (F[i-1][j] + C(i-1+j, i-1)) % mod;
F[i][j] = (F[i][j] + add) % mod;
}
printf("%d\n", F[N][M]);
return 0;
}