zoukankan      html  css  js  c++  java
  • BZOJ1042 [HAOI2008]硬币购物 完全背包 容斥原理

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1042


    题目概括

      硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买si的价值的东西。请问每次有多少种付款方法。


    题解

      一开始没看数据范围,觉得是类似状压的dp。

      然后看了看数据范围,懵逼了。

      然后发现可以写容斥!

      我们先当作完全背包,不考虑限制,把花费每种价格的方案数弄出来。

      然后容斥一下就可以了。

      具体容斥:所有情况 - 第一种货币超限的 - 第二种货币超限的…… + 第1、2种货币都超限的………………


    代码

    连续5次1A了,庆祝一下。

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int N=100000,N_size=N+5;
    int c[4],tot,d[4],s;
    LL dp[N_size];
    int main(){
        scanf("%d%d%d%d%d",&c[0],&c[1],&c[2],&c[3],&tot);
        memset(dp,0,sizeof dp);
        dp[0]=1;
        for (int i=0;i<4;i++)
            for (int j=0;j<=N;j++)
                if (j+c[i]<=N)
                    dp[j+c[i]]+=dp[j];
        while (tot--){
            scanf("%d%d%d%d%d",&d[0],&d[1],&d[2],&d[3],&s);
            LL ans=0;
            for (int i=0;i<(1<<4);i++){
                int v=s,cnt=0;
                for (int j=0;j<4;j++)
                    if ((i>>j)&1)
                        cnt++,v-=(d[j]+1)*c[j];
                if (v<0)
                    continue;
                if (cnt&1)
                    ans-=dp[v];
                else    
                    ans+=dp[v];
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    【LeetCode】085. Maximal Rectangle
    哈希查找
    堆排序
    归并排序
    希尔排序
    快速排序
    堆区和栈区,malloc和new的区别
    C++基础
    二分查找
    冒泡排序
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1042.html
Copyright © 2011-2022 走看看