zoukankan      html  css  js  c++  java
  • BZOJ 1042: [HAOI2008]硬币购物 容斥原理+背包

    Description

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

    题解:

    容斥原理公式:(源自百度百科)

    十分喜欢这道题,真的非常巧妙.
    不加限制,该题会变得特别模板.
    有限制后,似乎正着求有些困难,我们就考虑反着求,即简单容斥一下.
    我们先求出不加限制的方案数,再将不合法的方案数依次减掉.
    考虑容斥原理:
    总方案 - $sum$ 1个不合法 + $sum$ 2个不合法 - $sum$ 3个不合法......
    假设不加限制的总个数为 $N$ ,第一物品的限制为 $d$ (一共4个物品),那么当我们拿 $d+1$,$d+2$.... 个物品的时候开始不合法.
    也就是说,不合法的情况下,我们至少拿 $d+1$ 个1物品,剩下的由 1,2,3,4随便拼凑.
    而剩下的四个物品随便拼凑不就是 $DP[N-(d+1)*val_{1}]$ 嘛......
    其余情况同理.

    Code:

    #include<bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define maxn 1000000 
    #define N 200000 
    #define ll long long 
    using namespace std;
    int c[5],d[5]; 
    ll dp[maxn]; 
    int main(){
        //setIO("input"); 
        for(int i=0;i<4;++i) scanf("%d",&c[i]);  
        dp[0]=1; 
        for(int i=0;i<4;++i) for(int j=c[i];j<=N;++j) dp[j]+=dp[j-c[i]];                           
        int T;  
        scanf("%d",&T);
        while(T--){
            for(int i=0;i<4;++i) scanf("%d",&d[i]); 
            int res;  
            scanf("%d",&res);       
            ll ans=0;  
            for(int i=0;i<16;++i){
                int cnt=0,cur=res; 
                for(int j=0;j<4;++j) if((i>>j)&1) cnt^=1,cur-=(d[j]+1)*c[j]; 
                if(cur<0) continue; 
                if(cnt) ans-=dp[cur]; else ans+=dp[cur]; 
            }
            printf("%lld
    ",ans); 
        }
        return 0; 
    }
    

      

  • 相关阅读:
    JAVA多线程(七) ReentrantLock原理分析
    JAVA多线程(六) synchronize原理分析
    JAVA多线程(五) volatile原理分析
    pandas
    从美国总经理,到三一重卡的董事长,梁林河的重卡梦
    【转载】低水平领导的十大表现
    kill及其衍生程序
    python -m venv 的使用
    Python多版本启动器
    Pyinstaller最流行的打包程序
  • 原文地址:https://www.cnblogs.com/guangheli/p/10905787.html
Copyright © 2011-2022 走看看