http://poj.org/problem?id=3046
 就是这种模型:
 给      N 种物品,每种有      ai 个,从中选出      m 个,求方案数?
 参考博客:https://blog.csdn.net/ac_hell/article/details/51405598
 还是直接来样例比较直接:
 样例就是:有 两个      1,两个      2 ,一个      3,问从中选      2 个数 加上 从中选      3 个数的方案数之和
      dp[i][j] 表示从前      i 种物品中,选出      j 个的方案数
 那就是求      dp[3][2]+dp[3][3]
求      dp[3][2]:
 就是当前在处理第三种物品
 假如这次第三种物品一个都不拿,那么方案数就是     dp[2][3−0]
 假如这次第三种物品拿      1 个,那么方案数就是     dp[2][3−1]
 假如这次第三种物品拿      2 个,那么方案数就是     dp[2][3−2]
 依次类推。。。。
 所以方程就出来了:
dp[i][j]=dp[i−1][j−0]+ d[i−1][j−1]+dp[i−1][j−2]+.....+dp[i−1][j−j]
但是这道题的妙点在于优化(虽然好像不优化也能过)
优化
而后面这一坨红色的是不是相当于 从拿       1 个,拿       2 个。。。。直到拿完,
 而我们的       dp 是从拿       0 个开始,直到拿完,是不是感觉只有一点点的差别
那我们的       j 比原来少拿一个,变成       j−1,不是就相当于从       0 个开始拿了么~~~
 所以后面这一坨红色的其实是        dp[i][j−1]
<mark>那么方程就变成了: dp[i][j]=dp[i−1][j−0]+ dp[i][j−1]</mark>
这个方程就是主要的思路,然后就是一些细节问题了,比如我们这里的         dp[3][2],第         3 个物品最多才         1 个,怎么能拿         2 个哇,
 所以当当前这一种个数不够的时候就要减去那么多,就变成:
 <mark>         dp[i][j]=dp[i−1][j−0]+          dp[i][j−1]−dp[i−1][j−1−c]</mark>
诶不对啊,后面多的不一定只有 j-1-c 这一个啊,万一还多了 j-2-c,j-3-c,这些怎么办喃?为啥就只减去这一项?还是有点没想通
#include"iostream"
#include"string.h"
using namespace std;
const int MOD=1e6;
const int maxn=1e3+5;
int dp[2][maxn*maxn];
int a[maxn];
int main()
{
    int N,ge,qL,qR;
    while(cin>>N>>ge>>qL>>qR)
    {
        memset(a,0,sizeof(a));
        for(int i=1;i<=ge;i++)
        {
            int t;
            cin>>t;
            a[t]++;
        }
        int pre=0,now=0;
        memset(dp,0,sizeof(dp));
        dp[0][0]=dp[1][0]=1;
        int M=0;
        for(int i=1;i<=N;i++)
        {
            now=pre^1;
            M+=a[i];
            for(int j=1;j<=M;j++)
            {
                if(j<=a[i])dp[now][j]=dp[pre][j]+dp[now][j-1];
                else dp[now][j]=dp[pre][j]+dp[now][j-1]-dp[pre][j-1-a[i]];
                dp[now][j]=(dp[now][j]%MOD+MOD)%MOD;
            }
            pre=now;
        }
        long long ans=0;
        for(int i=qL;i<=qR;i++)
        {
            ans+=dp[now][i];
            if(ans>MOD)ans%=MOD;
        }
        cout<<ans<<endl;
    }
}
 
京公网安备 11010502036488号