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

    Description:

    方程$a_1 x_1+a_2x_2+a_3x_3+a_4x_4=s, $ (a_1),(a_2),(a_3),(a_4)给定
    对于 (q)(d_1)~(d_4)(s) 求满足(x_1<=d_1), (x_2<=d_2), (x_3<=d_3), (x_4<=d_4)正整数解的个数

    Hint:

    (d_i<=1e5), (s<=1e5), (q<=1e3)

    solution:

    多重背包显然超时
    考虑补集转化,求所有正整数解的个数-不满足di限制的个数
    (S_i)(x_i>d_i)的解的个数,(f[x])(x)时的正整数解
    即求(S_1∪S_2∪S_3∪S_4=∑S_i-∑S_i∩S_j+∑S_i∩S_j∩S_k-)......
    可以(2^4)枚举(s-(d_i+1)*a_i)......的(f[])和,再用(f[s])减去即可
    至于(f[]),一遍预处理即可

    #include<bits/stdc++.h>
    #define long long int
    using namespace std;
    const int mxn=1e5+5;
    int f[mxn],a[5],d[5],t,s;
    
    signed main()
    {
    	scanf("%d %d %d %d %d",&a[1],&a[2],&a[3],&a[4],&t);
    	f[0]=1;
    	for(int i=1;i<=4;++i) 
    		for(int j=a[i];j<=mxn-5;++j) 
    			f[j]+=f[j-a[i]];		//无限背包预处理
    	for(int i=1;i<=t;++i) {
    		scanf("%d %d %d %d %d",&d[1],&d[2],&d[3],&d[4],&s);
    		int ans=0;
    		for(int j=0;j<16;++j) { //枚举子集
    			int cnt=0,tp=s;
    			for(int k=0;k<4;++k) 
    				if((j>>k)&1) ++cnt,tp-=(d[k+1]+1)*a[k+1];
    			if(tp<0) continue ;	
    			if(cnt&1) ans-=f[tp]; //容斥
    			else ans+=f[tp];
    		} 
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Shell与if相关参数
    Linux盘符漂移问题
    shell脚本,每5个字符之间插入"|",行末不插入“|”
    paste:linux合并两个文件中的列(左右合并)
    关于bc 的scale .
    RxJS与观察者模式
    什么是虚拟DOM
    JS设计模式
    JS自定义事件
    原生js实现拖拽功能
  • 原文地址:https://www.cnblogs.com/list1/p/10361498.html
Copyright © 2011-2022 走看看