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

    (yysy) ,这个题真的是个不错的题目

    Description

    link

    给定 (4) 种面值的硬币,然后有 (n) 次询问

    每次给四个参数和一个面值,求每种硬币不使用超过参数个时凑成给定面值有多少方案

    Solution

    首先我们发现每次算方案显然是会飞的

    然后我们可以先上来做一次完全背包,在每次询问的时候容斥

    (就是(FlashHu)大佬的“询问重复利用信息”)

    我们发现每次多出来的不合法方案在每种硬币使用超量的时候

    所以我们就用状压 (+) 统计答案即可

    说不清,具体看代码吧……

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	int c[5],d[5],s,T,f[100010];
    	signed main()
    	{
    		for(int i=1;i<=4;++i) c[i]=read(); T=read(); f[0]=1;
    		for(int i=1;i<=4;++i) 
    		{
    			for(int j=c[i];j<=1e5;++j) f[j]+=f[j-c[i]];
    		}
    		while(T--)
    		{
    			for(int i=1;i<=4;++i) d[i]=read(); s=read();
    			int ans=f[s];
    			for(int i=1;i<=15;++i)
    			{
    				int del=0,t=s;
    				for(int j=1;j<=4;++j)
    				{
    					if(i&(1<<(j-1))) del++,t-=c[j]*(d[j]+1);
    				} 
    				if(t<0) continue;
    				if(del&1) ans-=f[t];
    				else ans+=f[t];
    			}cout<<ans<<endl;
    		}
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    

    Review

    我们在思考题目的时候可以预处理已知信息来对付重复询问

    另外:需要学习枚举子集的方法

  • 相关阅读:
    创建对象的七种方式
    设计模式之工厂模式
    设计模式之单例模式
    排序算法之插入排序
    排序算法之选择排序
    类及对象初体验
    排序算法之冒泡排序
    迭代器和生成器
    装饰器
    函数进阶
  • 原文地址:https://www.cnblogs.com/yspm/p/12740858.html
Copyright © 2011-2022 走看看