[HAOI2008]硬币购物

摘要:
题面在这里description硬币购物一共有4种硬币。每次带di枚ci硬币,买si的价值的东西。datarange[d_i,sle100000,Tle1000]solution使用单调队列优化多重背包十分开心地获得了20分的好成绩为什么我就松不过呢?综上,我们得到了一个的算法,可以通过本题。code多重背包(娱乐向)的代码#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#defineFILE"a"#definempmake_pair#definepbpush_back#defineRGregister#defineilinlineusingnamespacestd;typedefunsignedlonglongull;typedefvectorVI;typedeflonglongll;typedefdoubledd;constddeps=1e-10;constintmod=1e9+7;constintN=3010;constddpi=acos(-1);constintinf=2147483647;illlread(){RGlldata=0,w=1;RGcharch=getchar();while(ch!

题面在这里

description

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

data range
[d_i,sle 100000,Tle 1000 ]
solution

使用单调队列优化多重背包十分开心地获得了20分的好成绩
(O(4Ts))为什么我就不过呢?

观察数据,物品数量(=4),考虑对于物品数量的指数级算法,容斥
如果没有物品数量的限制,那么此题变成了一个完全背包问题,直接求解即可
现在的关键是物品的数量有限制,因此考虑如何去掉物品数量过多的一部分

考虑把总容量减去单件物品目前能够达到的最大容量(即(s-d_i imes c_i)),对剩下的空间做完全背包,
我们能够从这个方案数中得到仍然含有这个物品的方案数(使用(f[s][t])(t)的二进制位表示物品状况),
那么这个方案应该会等于开始的背包中这件物品数量过多的方案。

update:我还是太菜了。。。其实不用考虑s,这个方案就等于(f[s-(d_i+1) imes c_i])

我们使用总数-不合法,就会得到这件物品不超过(d_i)的方案数

接下来考虑有两种物品同时超过的情况
如果我们仅仅使用刚才的算法计算出(f[0][s]-sum_{i=1}^{4}f[2^{i-1}][s-c_i imes d_i]),
那么一种有两种物品同时超过的方案会被减去计算两次,加上即可
同理,减去三种物品同时超过的方案,加上四种物品同时超过的方案,我们就得到了我们要求的东西。

综上,我们得到了一个(O(2^k imes s+2^{2k} imes tot))((k)代表物品数量)的算法,
可以通过本题。

code

多重背包(娱乐向)的代码

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=3010;
const dd pi=acos(-1);
const int inf=2147483647;
il ll read(){
	RG ll data=0,w=1;RG char ch=getchar();
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
	return data*w;
}

il void file(){
	srand(time(NULL)+rand());
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
}

ll c[5],d[5],f[100010];
queue<ll>Q;
il ll DP(ll V){
	memset(f,0,sizeof(f));f[0]=1;
	for(RG int i=1;i<=4;i++){
		RG ll sum,ret;
		for(RG ll j=0;j<c[i];j++){
			sum=0;while(!Q.empty())Q.pop();
			for(RG ll k=0;k<d[i]&&(V-j)/c[i]*c[i]+j-k*c[i]>=0;k++){
				Q.push((V-j)/c[i]*c[i]+j-k*c[i]);
				sum+=f[(V-j)/c[i]*c[i]+j-k*c[i]];
			}
			for(RG ll k=(V-j)/c[i]*c[i]+j;k>=0;k-=c[i]){
				ret=f[k];
				if(k-c[i]*d[i]>=0){Q.push(k-c[i]*d[i]);sum+=f[k-c[i]*d[i]];}
				f[k]=sum;sum-=ret;Q.pop();
			}
		}
	}
	return f[V];
}

int main()
{
	RG ll T,s;
	for(RG int i=1;i<=4;i++)c[i]=read();T=read();
	while(T--){
		for(RG int i=1;i<=4;i++)d[i]=read();s=read();
		printf("%lld
",DP(s));
	}
	return 0;
}

(AC)代码

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=3010;
const dd pi=acos(-1);
const int inf=2147483647;
il ll read(){
    RG ll data=0,w=1;RG char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    return data*w;
}

il void file(){
    srand(time(NULL)+rand());
    freopen(FILE".in","r",stdin);
    freopen(FILE".out","w",stdout);
}

ll c[5],d[5];
ll f[16][100010];

il void update(ll &a,ll b){a+=b;}
il void init(){
    memset(f,0,sizeof(f));f[0][0]=1;
    for(RG int i=1;i<=4;i++)
        for(RG int v=0;v+c[i]<=100000;v++)
            for(RG int s=0;s<(1<<4);s++)
                update(f[s|(1<<(i-1))][v+c[i]],f[s][v]);
}

il ll DP(ll V){
    RG ll now,cnt,sum=0;
    for(RG int i=0;i<(1<<4);i++){
        now=V;cnt=0;
        for(RG int j=1;j<=4;j++)
            if(i&(1<<(j-1)))cnt++,now-=c[j]*d[j];
        if(now<0)continue;
        for(RG int j=0;j<(1<<4);j++)
            if((i&j)==i){
                if(cnt&1)sum-=f[j][now];
                else sum+=f[j][now];
            }
    }
    return sum;
}

int main()
{
    RG ll T,s;
    for(RG int i=1;i<=4;i++)
        c[i]=read();
    init();
    
    T=read();
    while(T--){
        for(RG int i=1;i<=4;i++)
            d[i]=read();
        s=read();
        printf("%lld
",DP(s));
    }
    return 0;
}

免责声明:文章转载自《[HAOI2008]硬币购物》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇DLL发布 matlab代码发布RT-Thread 在stm小内存系列产品的nano+msh完整移植教程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

Fiddler断点应用

对于不需要修改的报文,我们可以手动完成发送,fiddler会把拦截的网页发送到服务器或者客户端,需要修改的报文,可以在Fiddler修改完成后,再选择转发。另外,我们也可以使用Fiddler的断点功能模拟网络中断场景,验证服务器超时,客户端的处理情况。Afterresponses:服务器响应之后,在fiddler将响应传回给客户端之前。...

MeteoInfo-Java解析与绘图教程(一)

MeteoInfo-Java解析与绘图教程(一)已经进入开发行业很多年了,这两年一直从事气象开发行业,为此对气象绘图有了新的见解像色斑图与卫星图一直都有python去绘制,在偶然的情况下,我接触到了meteoInfo,在对其使用过程中,也可以做到用java绘制格点散点图,色斑图,等值图,卫星图,风场图所以趁这个机会我开始记录自己的探索过程,方便你我他对于绘图...

Systemd简介与使用

Systemd在并行启动中采用了比Upstart更激进的方案。图2显示了systemd的并行启动模式。它允许所有配置的服务同时启动。事实上,大多数使用systemd的现代发行版都与此类似。系统通过配置这些单元来切换和管理服务。...

ESXi挂载NFS共享存储

使用万兆交换机,ESXi使用NFS协议连接存储。本文介绍的是通过NFS协议挂载共享存储上的VS01卷,共享存储上已经赋予ESXi主机访问该卷的权限。...

echarts折线图 鼠标移入改变小点显示样式

=undefined){res+=nameList[i].seriesName+':'+nameList[i].data+'%'+''}}res=res.split;returnres[0]+''+res[1];}}echarts折线图的鼠标移动上去小点显示样式修改tooltip:{trigger:'axis',formatter:function{varr...

安装gulp教程(整理)

所以安装nodejs。...