大致题意:给n. m. l, y,n 种数,m个数, 问长度为 l 到 r 的序列有多少个
做法:d[i][j]表示从前i种选出j个的序列有多少个,dp[i][j] = sigma(dp[i-1][j-k]), k从0,到cont[i],因为数组太大,所以利用前缀和, 在加上滚动数组。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 1000000;
const int M = 100100;
int dp[2][M], n, m, l, r;
int cont[M];
int main(){
int i, j;
while(scanf("%d%d%d%d", &n, &m, &l, &r) == 4){
memset(cont, 0, sizeof(cont));
dp[0][0] = 1;
int a;
for(i = 1; i <= m; i++){
scanf("%d", &a);
cont[a] ++;
}
int nex, cur, sum;
sum = cur = 0;
nex = 1;
for(i = 1; i <= n; i++){
if(!cont[i]) continue;
sum += cont[i];
for(j = 0; j <= sum; j++){
if(j)
dp[cur][j] = (dp[cur][j] + dp[cur][j-1]) % mod;
if(j-cont[i]-1 >= 0)
dp[nex][j] = (dp[cur][j] + mod - dp[cur][j-cont[i]-1]) % mod;
else
dp[nex][j] = dp[cur][j];
}
swap(cur, nex);
}
int ans = 0;
for(i = l; i <= r; i++){
ans = (ans + dp[cur][i]) % mod;
}
printf("%d\n", ans);
}
return 0;
}