poj3046 划分数dp

来源:互联网 发布:猎头搜 知乎 编辑:程序博客网 时间:2024/04/27 14:58

题目链接:点击打开链接


题意:

有 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 secondint 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;}


0 0
原创粉丝点击