zoukankan      html  css  js  c++  java
  • BZOJ 1042 [HAOI2008]硬币购物(完全背包+容斥)

    题意:

    4种硬币买价值为V的商品,每种硬币有numi个,问有多少种买法

    1000次询问,numi<1e5

    思路:

    完全背包计算出没有numi限制下的买法,

    然后答案为dp[V]-(s1+s2+s3+s4)+(s12+s13+s14+s23+s24+s34)-(s123+s124+s134+s234)+s1234
    其中s...为某硬币超过限制的方案数
    求s的方法:
    如s1:硬币1超过限制,就是硬币1至少选了num1+1个,其他随便,所以s1=dp[V-c1*(num1+1)]
    同理s12 = dp[V - c1 * (num1 + 1) - c2 * (num2 + 1)]
    代码:
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 2e6+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    ll dp[maxn];
    ll c[5];
    ll v[maxn];
    ll num[5];
    ll ans,V;
    //dfs搜容斥组合
    void dfs(int x, int k, ll sum){//搜到第x个,已经选了k个,当前组合一共需要减sum
        //printf("%d %d %lld
    ",x,k,sum);
        if(V-sum < 0)return;
        if(x==5){
            //容斥判断该加还是减
            if(k==0)return;
            if(k&1) ans += dp[V-sum];
            else ans -= dp[V-sum];
            return;
        }
        dfs(x+1, k, sum);//当前不选
        dfs(x+1,k+1,sum+c[x]*(num[x]+1));//
    }
    int main(){
        for(int i = 1; i <= 4; i++){
            scanf("%lld", &c[i]);
        }
        int T;
        scanf("%d", &T);
        dp[0] = 1;
        for(int i = 1; i <= 4; i++){
            for(int j = 0; j <= maxn; j++){
                if(j-c[i]>=0)dp[j] += dp[j-c[i]];
            }
        }
        while(T--){
            for(int i = 1; i <= 4; i++){
                scanf("%lld", &num[i]);
            }
            scanf("%lld", &V);
            ans = 0;
            dfs(1, 0, 0);
            printf("%lld
    ",dp[V]-ans);
        }
        return 0;
    }
    
    /*
    1 2 5 10 1
    3 2 3 1 10
    
     */

    [HAOI2008]硬币购物否

  • 相关阅读:
    how to pass a Javabean to server In Model2 architecture.
    What is the Web Appliation Archive, abbreviation is "WAR"
    Understaning Javascript OO
    Genetic Fraud
    poj 3211 Washing Clothes
    poj 2385 Apple Catching
    Magic Star
    关于memset的用法几点
    c++ 函数
    zoj 2972 Hurdles of 110m
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10117233.html
Copyright © 2011-2022 走看看