poj3046 劃分數dp

題目鏈接:點擊打開鏈接


題意:

有 T 種螞蟻家庭;

每個家庭 ai 個螞蟻;

給你一串序列,相同的數字代表是一個家庭;

問你這一串序列能組成多少不同的(1 ~ T)的集合;


理解:

雲裏霧裏;

書上原題;

是 dp 的多重集組合數;

直接套模板;

遞推式:dp[i + 1][j] = sigma(dp[i][j - k]);

其中 k 是 [0, min(j, a[i])];

變形如下:

dp[i + 1][j] = dp[i + 1][j - 1] + dp[i][j] - dp[i][j - 1 - a[i]];

其中 j 要滿足條件 j - 1 - a[i] >= 0;


代碼如下:


#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int MIN_INF = 1e-7;
const int MAX_INF = (1e9) + 7;

#define X first
#define Y second

int dp[2][100100];
int ha[1010];
const int M = 1000000;

int main() {
    int t, a, s, b;
    cin >> t >> a >> s >> b;
    for (int i = 0; i < a; ++i) {
        int x;
        cin >> x;
        ++ha[x];
    }

    dp[0][0] = 1;
    dp[1][0] = 1;

    int k = 0;
    for (int i = 1; i <= t; ++i) {
        for (int j = 1; j <= a; ++j) {
            if (j - 1 - ha[i] >= 0) {
                dp[(k + 1) % 2][j] = (dp[(k + 1) % 2][j - 1] + dp[k][j] - dp[k][j - 1 - ha[i]] + M) % M;
            }
            else {
                dp[(k + 1) % 2][j] = (dp[(k + 1) % 2][j - 1] + dp[k][j]) % M;
            }
        }
        k = (k + 1) % 2;
    }

    int ans = 0;
    for (int i = s; i <= b; ++i) {
        ans = (ans + dp[k][i]) % M;
    }
    cout << (ans + M) % M << endl;

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章