您的位置:首页 > 其它

POJ 3046 Ant Counting(递推,和号优化)

2015-10-17 12:38 381 查看
计数类的问题,要求不重复,把每种物品单独考虑。

将和号递推可以把转移优化O(1)。

f[i = 第i种物品][j = 总数量为j] = 方案数

f[i][j] = sigma{f[i-1][j-k],(k = [0,min(j,c[i])])}
把和号展开
f[i][j] : j-0,j-1,...,j-a[i]
f[i][j-1] : j-1,j-2,...,j-a[i]-1
中间部分是一样的可以避免重复计算。

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
//#include<bits/stdc++.h>
using namespace std;

int T, A, S, B;
const int maxt = 1e3+5, maxa = 1e5+5, mod = 1e6;
int f[2][maxa];
int c[maxt];

//#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
scanf("%d%d%d%d",&T,&A,&S,&B);
for(int i = A; i--;){
int x; scanf("%d",&x);
c[x]++;
}
f[0][0] = f[1][0] = 1; //不选方案数为1
for(int i = 1; i <= T; i++){
int a = i&1, b = a^1;
for(int j = 1; j <= B; j++){
if(j-c[i]>0){
f[a][j] = ( f[a][j-1] + f[b][j] - f[b][j-1-c[i]] ) % mod;
}else {
f[a][j] = ( f[a][j-1] + f[b][j] ) % mod;
}
}
}
int sum = 0, *F = f[T&1];
for(int i = S; i <= B; i++){
sum = (sum + F[i]) % mod;
}
printf("%d\n",sum<0?sum+mod:sum);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: