您的位置:首页 > 其它

POJ 3046 Ant Counting

2017-08-15 20:13 399 查看

题意:给出T种数字。每种各有N[i]个。然后用这些数字构成一些序列, 问x长度到y长度的序列有多少种

思路:

dp[i][j] 表示前i种数字构成长度为j的序列有多少种。

dp[i][j] = sigma(dp[i - 1][j - k]) k的范围是0~N[i]    

//前i-1个家族配成j-k的集合,每一个集合都加入家族i的k只的蚂蚁,累加得到前i个家族配成j的集合的个数:

#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <algorithm>
using namespace std;
#define MOD 1000000
int family[1001];
int dp[1001][10001];

int main()
{
int T,A,S,B;
cin>>T>>A>>S>>B;
for(int i=0;i<A;i++)
{
int index;
cin>>index;
++family[index];
}
dp[0][0]=1;// 空集的个数为一
int totel=family[0];
for(int i=1;i<=T;i++)
{
totel+=family[i]; // 前i个家族一共有多少只蚂蚁
for(int k=0;k<=family[i];k++)
{
for(int j=totel;j>=k;j--)
{
dp[i][j]=(dp[i][j]+dp[i-1][j-k])%MOD; // 前i-1个家族配成j-k的集合们每一个集合都放入k只
}
}
}
int result=0;
for (int i = S; i <= B; ++i)
{
result = (result + dp[T][i]) % MOD;
}
cout << result << endl;
return 0;
}

因为总共的数字个数可能有10W个,有1000种数组。所以需要开滚动数组来做

//由于dp数组每次都是i和i-1,所以可以利用奇偶性实现滚动数组:
int dp[2][100001];

int cur = i & 1;
int pre = (i - 1) & 1;
memset(dp[cur], 0, sizeof(dp[cur]));
dp[cur][j] = (dp[cur][j]+ dp[pre][j - k]) % MOD;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: