1. 程式人生 > 實用技巧 >Codeforces Round #240 (Div. 1) B. Mashmokh and ACM (DP)

Codeforces Round #240 (Div. 1) B. Mashmokh and ACM (DP)

  • 題意:給出兩個正整數\(n\)\(k\),構造一個長度為\(k\)的好序列\(b_1,b_2,...,b_k(1\le b_1\le b_2\le ...\le b_k \le n)\),並且滿足\(b_i|b_{i+1}\),問最多能夠造出多少這樣的序列(同一個元素可以出多次).

  • 題解:我們記\(dp[i][j]\)表示長度為\(i\),序列末尾是\(j\)的好序列個數,首先,每個數自己可以構成一個好序列,我們先將\(dp[1][i]=1 \ (1\le i\le n)\),然後列舉序列長度\([2,k]\),\(j\)表示因子,\(j*k\)表示我們序列末尾的數,每個數的狀態都可以由序列長度為\(i-1\)

    的它的因子\(j\)轉移而來,所以我們可以寫出狀態轉移方程\(dp[i][j*k]=dp[i][j*k]+dp[i-1][j]\).

  • 程式碼:

    int n,k;
    int dp[2010][2010];
    int ans;
    
    int main() {
        //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        n=read(),k=read();
        for(int i=1;i<=n;++i) dp[1][i]=1;
    
        for(int i=2;i<=k;++i){
            for(int j=1;j<=n;++j){
                for(int k=1;k*j<=n;++k){
                    dp[i][k*j]=(dp[i][k*j]+dp[i-1][j])%mod;
                }
            }
        }
    
        for(int i=1;i<=n;++i){
            ans=(ans+dp[k][i])%mod;
        }
    
        printf("%d\n",ans);
    
        return 0;
    }