• 【BZOJ1042】硬币购物(动态规划,容斥原理)


    【BZOJ1042】硬币购物(动态规划,容斥原理)

    题面

    BZOJ

    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

    题解

    真题真好啊。

    先不考虑任何有关于硬币个数的限制
    (f[i])表示没有任何限制的情况下,价格为(n)的方案数
    直接做一个背包就行了。

    现在加上限制来看,我们用总方案减去不合法。
    总方案是(f[n]),不合法呢?
    某一个硬币如果不合法,那么它就要用(d+1)
    剩下的随便选,也就是(f[n-c*(d+1)])
    这样直接容斥计算即可。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    int c[4],d[4],S;
    ll f[111111];
    int main()
    {
    	for(int i=0;i<4;++i)c[i]=read();
    	f[0]=1;
    	for(int k=0;k<4;++k)
    		for(int j=c[k];j<=100000;++j)
    			f[j]+=f[j-c[k]];
    	int Q=read();
    	while(Q--)
    	{
    		for(int i=0;i<4;++i)d[i]=read();S=read();
    		ll ss,ans=0;
    		for(int i=0,tt;i<16;++i)
    		{
    			ss=tt=0;
    			for(int j=0;j<4;++j)
    				if(i&(1<<j))++tt,ss+=(d[j]+1)*c[j];
    			if(ss>S)continue;
    			(tt&1)?ans-=f[S-ss]:ans+=f[S-ss];
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    VSCode拓展插件推荐(HTML、Node、Vue、React开发均适用)
    算法_栈的Java的通用数组实现
    算法_计算输入的算术表达式的值.
    设计模式整理_组合模式
    JavaSE复习_9 集合框架复习
    一个小题目的三种不同的解法
    设计模式整理_状态模式
    设计模式整理_迭代器模式
    设计模式整理_模板模式
    JavaSE复习_8 泛型程序设计
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8656700.html
Copyright © 2020-2023  润新知