zoukankan      html  css  js  c++  java
  • [HAOI2008]硬币购物

    洛咕

    题意:硬币购物一共有(4)种硬币.面值分别为(c_1,c_2,c_3,c_4).某人去商店买东西,去了(tot)次.每次带(d_i)(c_i)硬币,买(s_i)的价值的东西.请问每次有多少种付款方法?(s_i<=100000).

    分析:预处理没有硬币枚数限制时(即完全背包)买(x)元的方案数.然后容斥是否超过硬币的限制即可.

    这道题的处理方式真的很妙,遇到这种本来有上界或者下界的东西,我们先求出它无限制时的答案,然后再容斥掉不符合限制的答案.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=100005;
    int c[5],d[5];ll f[N];//记得开long long
    int main(){
    	c[1]=read();c[2]=read();c[3]=read();c[4]=read();
    	int tot=read();f[0]=1;//完全背包初始化
    	for(int i=1;i<=4;++i)
    		for(int j=c[i];j<=N-5;++j)
    			f[j]+=f[j-c[i]];//完全背包,f[j]表示买j元的方案数
    	while(tot--){
    		d[1]=read();d[2]=read();d[3]=read();d[4]=read();
    		int sum=read();ll ans=0;
    		for(int i=0;i<=15;++i){//15=(2^4)-1,二进制枚举
    			ll t=sum;int cnt=0;
    			for(int j=1;j<=4;++j){//判断是否有该种硬币的限制
    				if(i&(1<<(j-1)))t-=c[j]*(d[j]+1),cnt^=1;
    			}
    			if(t<0)continue;//防止下面数组下标越界
    			if(!cnt)ans+=f[t];
    			else ans-=f[t];
    		}
    		printf("%lld
    ",ans);
    	}
        return 0;
    }
    
    
  • 相关阅读:
    python 面向对象(三大特性)
    python 发红包
    python 计算器
    python 模块和包
    python 异常处理
    python 序列化模块
    python 常用模块
    esriSRGeoCS3Type Constants
    esriSRGeoCS2Type Constants
    esriSRGeoCSType Constants
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11594662.html
Copyright © 2011-2022 走看看