洛谷P1450 [HAOI2008]硬币购物

2018-06-17 21:15:27来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

题目描述

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

输入输出格式

输入格式:

 

第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s

 

输出格式:

 

每次的方法数

 

输入输出样例

输入样例#1: 复制
1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900
输出样例#1: 复制
4
27

说明

di,s<=100000

tot<=1000

[HAOI2008]

 

首先考虑如果去掉限制,那就是一个裸的完全背包问题

加上限制的话,我们可以考虑先求出没有限制的,再把超出限制的减去

体现到代码上,就是dp[num]减去dp[num-C[i]*(D[i]+1)]

这样每个都减去

但是会有减重的部分,再加回去

 

 

#include<iostream>
#include<cstdio>
#define LL long long 
using namespace std;
const LL MAXN=1e6+10;
LL C[5],S[5];
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline LL read()
{
    char c=nc();LL x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
    return x*f;
}
LL dp[MAXN],ans;
void dfs(LL now,LL zt,LL num)
{
    if(num<0) return ;
    if(now==5)
    {
        if(zt&1) ans-=dp[num];
        else ans+=dp[num];
        return ;
    }
    dfs(now+1,zt+1,num-C[now]*(S[now]+1) );
    dfs(now+1,zt,num);
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    for(LL i=1;i<=4;i++) C[i]=read();
    dp[0]=1;
    for(LL i=1;i<=4;i++)
        for(LL j=C[i];j<=100001;j++)
                dp[j]+=dp[j-C[i]];
    LL K=read();
    while(K--)
    {
        for(LL i=1;i<=4;i++) S[i]=read();
        LL num=read();
        ans=0;
        dfs(1,0,num);
        printf("%lld\n",ans);
    
    }
    return 0;
}

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Qt 5.7.0 使用 QAxWidget 显示网页

下一篇:字符串形式的广义表的简单运算