zoukankan      html  css  js  c++  java
  • [bzoj1042][HAOI2008]硬币购物【dp】【容斥】

    【题目描述】

    Description

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

    Input

      第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000

    Output

      每次的方法数

    Sample Input

    1 2 5 10 2
    3 2 3 1 10
    1000 2 2 2 900

    Sample Output

    4
    27

    HINT

    Source

    【题解】

     记 f[i] 表示不考虑数量限制买价值为i的物品的方案数。

    由容斥原理可得 ans=f[i]-有一种越界的+有两种越界的-有三种越界的+有四种越界的

    越界的的计算方法:把它在限制内的全去掉,剩下的任意。

    /* --------------
        user Vanisher
        problem bzoj-1042
    ----------------*/
    # include <bits/stdc++.h>
    # define 	ll 		long long
    # define 	S 		100000
    using namespace std;
    ll read(){
    	ll tmp=0, fh=1; char ch=getchar();
    	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    	return tmp*fh;
    }
    ll c[5],d[5],n,f[S+10],s,ans;
    int main(){
    	c[1]=read(), c[2]=read(), c[3]=read(), c[4]=read(), n=read();
    	f[0]=1;
    	for (ll i=1; i<=4; i++)
    		for (ll j=c[i]; j<=S; j++)
    			f[j]=f[j]+f[j-c[i]];
    	for (ll i=1; i<=n; i++){
    		d[1]=read(), d[2]=read(), d[3]=read(), d[4]=read(); s=read();
    		ans=0;
    		for (ll j=0; j<(1<<4); j++){
    			ll now=s,ti=1;
    			for (ll k=1; k<=4; k++)
    				if ((j&(1<<(k-1)))>0) now=now-(d[k]+1)*c[k],ti=-ti;
    			if (now>=0) ans=ans+ti*f[now];
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    


  • 相关阅读:
    多线程实践
    sql你server,mysql,oracle的分页语句
    BS与CS的联系与区别
    EJB与JAVA BEAN的区别
    Struts2.0 xml文件的配置(package,namespace,action)
    Q 51~60
    Q 41~50
    列表推导式
    Q 31~40
    Q 21~30
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9136028.html
Copyright © 2011-2022 走看看