题意:有T种蚂蚁,总共A只,求将这些蚂蚁,分为数量为S,S+1,S+2,…,B的集合的总集合数。
突破口:
设置a[T]记录每种蚂蚁的数量,设置dp[i,j]表示,用前i种蚂蚁,构成数量为j的集合的最大集合数,那么,第i种蚂蚁有用0只,1只,…,a[T]只,因此,状态转移方程应为:
dp[i,j]=sum(dp[i-1,j~j-a[T]]).
代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e5+5,mod=1e6;
int dp[maxn],a[1005]; //注意,这里要用滚动数组,否则很可能会爆内存
int main()
{
int T,A,S,B,i,j,k;
int sum=0;
// printf("%d\n",mod); //哎呀,mod要等于1e6,一开始弄成1e7,找了好一段时间的bug
scanf("%d%d%d%d",&T,&A,&S,&B);
for(i=0;i<=T;i++)
a[i]=0;
for(int t,i=1;i<=A;i++)
{
scanf("%d",&t);
a[t]++;
dp[i]=0;
}
for(i=0;i<=a[1];i++)
dp[i]=1;
for(i=2;i<=T;i++)
{
for(j=B;j>=1;j--)
{
int sum1=0;
for(k=j;(k>=0)&&(k>=j-a[i]);k--)
sum1=(sum1+dp[k])%mod;
dp[j]=sum1%mod;
}
}
for(i=S;i<=B;i++)
sum=(sum+dp[i])%mod; //记得取模
printf("%d\n",sum);
return 0;
}
TIPS:没什么思路的时候可以手推,然后划出一个表来观察。一开始这么找到状态转移方程的。