CF1204E Natasha, Sasha and the Prefix Sums [動態規劃]

Natasha, Sasha and the Prefix SumsNatasha,\ Sasha\ and\ the\ Prefix\ Sums

題目描述見鏈接 .


\color{red}{正解部分}

F[i,j]F[i, j] 表示 ii11, jj1-1 的答案, 從後往前 放置數字進行 狀態轉移

  • 放置 11: 對 F[i,j]F[i, j] 產生 F[i1,j]+(i1+ji1)F[i-1, j] + \begin{pmatrix} i-1+j \\ i-1 \end{pmatrix} 的貢獻 .

  • 放置 1-1: 對 F[i,j]F[i, j] 產生 F[i,j1]((i+j1j1)g[i,j1])F[i, j-1] - \left( \begin{pmatrix} i+j-1 \\ j-1 \end{pmatrix} - g[i, j-1]\right) 的貢獻 .

  • 初值: F[i,0]=iF[i, 0] = i

其中 g[i,j]g[i, j] 表示 ii11, jj1-1 所組成的序列 最大前綴和00 的方案數, 先考慮特殊情況,

  • i>ji > j, g[i,j]=0g[i, j] = 0 .
  • g[0,0]=1g[0, 0] = 1

再考慮 iji \le j 時, g[i,j]g[i, j] 能更新哪些狀態,

  • 11 時, 若能更新 g[i+1,j]g[i+1, j], 則說明 i<ji < jiji \le j, 所以轉移條件爲 i<ji < j .
  • 1-1 時, 若能更新 g[i,j+1]g[i, j+1], 則說明 iji \le jij+1i \le j+1, 所以轉移條件爲 iji \le j .

ij\therefore i \le j 時, g[i,j]=g[i1,j]+g[i,j1]g[i, j] = g[i-1, j] + g[i, j-1] .

因爲 i1<ji-1 < j, g[i1,j]g[i-1, j] 一定是由於取 maxmax 取到 00 的,
而原本最大前綴和爲 00, 多放置一個 1-1, 最大前綴和仍爲 00,
因此當 iji \le j 時, 放置 11 和 放置 1-1 都可以轉移到 g[i,j]g[i, j] .


\color{red}{實現部分}

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章