• HAOI2008 硬币购物


    题目链接:戳我

    讲道理,虽然是一个蓝题,但是以后看见方案计数问题还是要想一想容斥的......
    就是......我们知道如果个数不限制的话,直接一个完全背包就万事了对吧。(就是和完全背包一样的方案计数问题,DP方程长得一样)
    但是这个题都个数限制......所以就GG了。
    现在我们考虑如何做这个个数限制。对于一个个数为(d_i)(c_i)硬币来说,如果它填充了大于等于((c_i) imes (d_i+1))的容量,显然这个方案是不合法的。
    我们先预处理一下总共的个数。
    所以我们用总共的减去不合法的就是答案了。
    但是有4种硬币,所以我们现在要考虑容斥了......就是减去至少一个不合法的,加上至少两个不合法的,减去至少三个不合法的,加上至少四个不合法的。
    好,完事了。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define MAXN 100000
    using namespace std;
    int tot,n;
    int num[5],c[5];
    long long dp[200010];
    inline int calc(int x){return (num[x]+1)*c[x];}
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&tot);
        // printf("%d %d %d %d %d
    ",c[1],c[2],c[3],c[4],tot);
        dp[0]=1;
        for(int i=1;i<=4;i++)
            for(int j=c[i];j<=MAXN;j++)
                dp[j]+=dp[j-c[i]];
        while(tot--)
        {
            scanf("%d%d%d%d%d",&num[1],&num[2],&num[3],&num[4],&n);
            // printf("%d %d %d %d %d
    ",num[1],num[2],num[3],num[4],n);
            long long ans=dp[n];
            // cout<<ans<<endl;
            if(n-calc(1)>=0) ans-=dp[n-calc(1)];
            if(n-calc(2)>=0) ans-=dp[n-calc(2)];
            if(n-calc(3)>=0) ans-=dp[n-calc(3)];
            if(n-calc(4)>=0) ans-=dp[n-calc(4)];
            if(n-calc(1)-calc(2)>=0) ans+=dp[n-calc(1)-calc(2)];
            if(n-calc(1)-calc(3)>=0) ans+=dp[n-calc(1)-calc(3)];
            if(n-calc(1)-calc(4)>=0) ans+=dp[n-calc(1)-calc(4)];
            if(n-calc(2)-calc(3)>=0) ans+=dp[n-calc(2)-calc(3)];
            if(n-calc(2)-calc(4)>=0) ans+=dp[n-calc(2)-calc(4)];
            if(n-calc(3)-calc(4)>=0) ans+=dp[n-calc(3)-calc(4)];
            if(n-calc(1)-calc(2)-calc(3)>=0) ans-=dp[n-calc(1)-calc(2)-calc(3)];
            if(n-calc(1)-calc(2)-calc(4)>=0) ans-=dp[n-calc(1)-calc(2)-calc(4)];
            if(n-calc(1)-calc(3)-calc(4)>=0) ans-=dp[n-calc(1)-calc(3)-calc(4)];
            if(n-calc(2)-calc(3)-calc(4)>=0) ans-=dp[n-calc(2)-calc(3)-calc(4)];
            if(n-calc(1)-calc(2)-calc(3)-calc(4)>=0) ans+=dp[n-calc(1)-calc(2)-calc(3)-calc(4)];
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    WebRTC学习笔记_Demo收集
    无法获取手机号码
    Hadoop-2.2.0中文文档——Common-Hadoop HTTP web控制台认证
    windows下安装,配置gcc编译器
    Effective C++笔记03:资源管理
    关于打印机状态的获取
    《学习opencv》笔记——矩阵和图像操作——cvInRange,cvInRangeS,cvInvert and cvMahalonobis
    winform Combobox出现System.Data.DataRowView的解决的方法
    CSDN积分规则具体解释--【叶子】
    HTML5中的Web Storage(sessionStorage||localStorage)理解与简单实例
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10861168.html
Copyright © 2020-2023  润新知