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

    题目传送门

    据说NOIP前写题解会(mathcal{RP})++


    看数据范围,肯定不能写多重背包,会(T)飞~
    如果每种硬币没有个数限制,就可以用完全背包了。

    正难则反,我们可以先用完全背包预处理,然后减去不合法的情况。不合法的情况就是一个(s-(d+1) imes c)的背包
    但如果我们直接减去,会导致重复计算。比如我们减去第一种超的和第二种超的,第一种和第二种都超的就被减了两次。所以要容斥

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long ans,f[100010],c[5],d[5];
    int read(){
    	int k=0; char c=getchar();
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9')
    	  k=k*10+c-48,c=getchar();
    	return k;
    }
    int main(){
    	for(int i=0;i<=3;i++) c[i]=read();
    	f[0]=1LL;  //完全背包预处理
    	for(int i=0;i<=3;i++)
    	  for(int j=c[i];j<=100001;j++)
    	    f[j]+=f[j-c[i]];
    	int t=read();
    	while(t--){
    		for(int i=0;i<=3;i++) d[i]=read();
    		int s=read(); ans=f[s];
    		for(int i=1;i<=15;i++){  //用子集枚举来容斥
    			int flag=0,num=s;
    			for(int j=0;j<=3;j++)
    			  if(i&(1<<j))
    				num-=(d[j]+1)*c[j],++flag; //减去不合法情况
    			if(num>=0)  //容斥:奇减偶加
    			  if(flag&1) ans-=f[num];
    			  else ans+=f[num];
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    存储结构接收数组
    oracle数据库sql根据查看执行计划优化sql--走不走索引
    多线程--Thread
    java常用集合族谱
    设计模式之二 适配模式
    Tomcat优化问题
    设计模式之一
    C++虚函数表,虚表指针,内存分布
    设计模式
    linux环境下的时间编程
  • 原文地址:https://www.cnblogs.com/morslin/p/11854992.html
Copyright © 2011-2022 走看看