[BZOJ1042]AOI2008]硬币购物

题目描述 Description

硬币购物一共有4种硬币。面值分别为\(c_1\) ,\(c_2\) ,\(c_3\) ,\(c_4\) 。某人去商店买东西,去了\(tot\) 次。每次带\(d_i\) 枚\(c_i\) 硬币,买\(s_i\) 的价值的东西。请问每次有多少种付款方法。

输入描述 Input Description

第一行 \(c_1\) ,\(c_2\) ,\(c_3\) ,\(c_4\) ,\(tot\) 下面\(tot\) 行 \(d_1\) ,\(d_2\) ,\(d_3\) ,\(d_4\) ,\(s\) ,

输出描述 Output Description

每次的方法数

样例输入 Sample Input

1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900

样例输出 Sample Output

4
27

数据范围及提示 Data Size & Hint

其中\(d_i,s<=100000,tot<=1000\)

之前的一些废话

退役的我回归了,但这次重返只是为了明天的比赛,时间虽短,但重新拾起这一切的我找到了5个月前为了梦想奋斗的自己,当时的自己热血沸腾,充满斗志,说真的,我无比热爱这种感觉,但这毕竟只是昙花一现,转瞬即逝的。

题解

背包问题带有这么多附属条件,还有数量限制,看起来好复杂啊。(谁叫我几个月没有碰OI,大脑生锈了呢)

但是如果不考虑数量限制,这就是一个很智障的背包问题了(md第一次打我循环顺序还打反了)

\(f_i\)表示不考虑任何限制,由四种硬币组成价值为i的方案数,转移为:$f[i]=\sum {f_{i-c_j}} (j \leq 4) $

显然这并不是最后的答案,因为这些方案里还藏着不少几类硬币超限的方案,于是我们需要用容斥原理把他们减掉

ans=\(f_s\) -(只有第一类硬币超的方案)--(只有第二类硬币超的方案)-(只有第三类硬币超的方案)-(只有第四类硬币超的方案)+(只有第一类第二类硬币超的方案)+..+

反正就是这四个集合的交加加减减

现在考虑如何算(只有第一类硬币超的方案)。当第一类硬币去到\(d_1+1\) 时那么一定就超了,剩下的空间就可以随便分配了,所以这个方案数$ =f_{s-c_1*(d_1+1)}$

其他的都类似。

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long LL;
#define mem(a,b) memset(a,b,sizeof(a))
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c==‘-‘)f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
const int maxn=5;
int c[maxn],d[maxn];
LL dp[100010];
int main()
{
    for(int i=0;i<4;i++)c[i]=read();
    dp[0]=1ll;
    for(int i=0;i<4;i++)
        for(int j=c[i];j<=100000;j++)dp[j]+=dp[j-c[i]];
    //for(int i=0;i<=10;i++)printf("DP:%d %d\n",i,dp[i]);
    //cout<<"fa"<<dp[100000]<<endl;
    int T=read();
    while(T--)
    {
        for(int i=0;i<4;i++)d[i]=read();
        int s=read();
        LL ans=0;
        for(int i=0;i<16;i++)
        {
            int cnt=0;
            LL tmp=0;
            for(int j=0;j<4;j++)
                if(i&(1<<j))cnt++,tmp+=(LL)c[j]*(LL)(d[j]+1);
            if(tmp>s)continue;
            if(cnt%2)ans-=dp[s-tmp];
            else ans+=dp[s-tmp];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

总结

大脑不再那么锈了

原文地址:https://www.cnblogs.com/FYH-SSGSS/p/8526127.html

时间: 2024-10-13 08:17:41

[BZOJ1042]AOI2008]硬币购物的相关文章

[bzoj1042][HAOI2008][硬币购物] (容斥原理+递推)

Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000 Output 每次的方法数 Sample Input 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 Sample Output 4 27 So

bzoj1042: [HAOI2008]硬币购物

好神的容斥原理 #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long int

BZOJ-1042: [HAOI2008]硬币购物 (背包DP+容斥原理)

1042: [HAOI2008]硬币购物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2888  Solved: 1777[Submit][Status][Discuss] Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,

【bzoj1042】硬币购物

容斥 #include<bits/stdc++.h> #define N 100005 typedef long long ll; using namespace std; ll ans,f[N]; int c[10],d[10],T; void dfs(int x,int k,int sum){ if(sum<0)return; if(x==5){ if(k&1)ans-=f[sum]; else ans+=f[sum]; return ; } dfs(x+1,k+1,sum-

【BZOJ1042】【DP + 容斥】[HAOI2008]硬币购物

Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s Output 每次的方法数 Sample Input 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 Sample Output 4 27 HINT 数据规模 di,s<=100000 tot<

【bzoj1042】【HAOI2008】【硬币购物】【dp】

Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s Output 每次的方法数 Sample Input 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 Sample Output 4 27 HINT 数据规模 di,s<=100000 tot<

【bzoj1042】[HAOI2008]硬币购物 背包dp+容斥原理

题目描述 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. 输入 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000 输出 每次的方法数 样例输入 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 样例输出 4 27 题解 背包dp+容斥原理 考虑没有硬币个数限制,那么本题显然是完全

【BZOJ1042】[HAOI2008]硬币购物 容斥

[BZOJ10492][HAOI2008]硬币购物 Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000 Output 每次的方法数 Sample Input 1 2 5 10 2 3 2 3 1 10 1000 2 2 2

[HAOI2008][BZOJ1042] 硬币购物

1042: [HAOI2008]硬币购物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1380  Solved: 814[Submit][Status][Discuss] Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s