题意:有 A 只蚂蚁分别属于 T 个家族,现在给出这 A 只蚂蚁的种类,求有多少种组合方法可以组合成 k 只蚂蚁,统计组合数量 [S,B] 区间的所有方法和,只输出最后六位数;
分析:这类组合问题,可以用生成函数或者DP做,DP的时间复杂度会低一些,设 ant[i] 表示第 i 中蚂蚁的数量,令 dp[i][j] 表示前 i 中蚂蚁组成数量为 j 的集合的方案数量,则初步转移方程不难想出来:
①dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+dp[i-1][j-2]+...+dp[i-1][j-ant[i]];
②dp[i][j-1]=dp[i-1][j-1]+dp[i-1][j-2]+dp[i-1][j-2]+...+dp[i-1][j-ant[i]-1];
所以,根据上面两个方程整合可以得出
Ⅰ:dp[i][j]=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-ant[i]-1];
代码:
#include<cstdio>
#include<iostream>
using namespace std;
const int MAXN = 1E5+10;
const int MOD = 1E6;
int f[2][MAXN];
int ant[1000+10];
int T,A,S,B;
int main()
{
scanf("%d%d%d%d",&T,&A,&S,&B);
for(int i=0;i<A;i++)
{
int v; scanf("%d",&v); ant[v]++;
}
f[0][0]=f[1][0]=1; //滚动数组优化空间
for(int i=1;i<=T;i++)
{
for(int j=1;j<=B;j++)
{
if(j-ant[i]-1>=0)
f[i&1][j]=f[i&1][j-1]+f[(i-1)&1][j]-f[(i-1)&1][j-ant[i]-1];
else
f[i&1][j]=f[i&1][j-1]+f[(i-1)&1][j];
f[i&1][j]=(f[i&1][j]+MOD)%MOD;
}
}
long long sum=0;
for(int i=S;i<=B;i++) sum+=f[T&1][i],sum%=MOD;
printf("%lld",sum);
}