zoukankan      html  css  js  c++  java
  • Luogu P1450 硬币购物 题解报告

    题目传送门

    【题目大意】

    有四种面值的硬币$c[1~4]$,现在要买$tot$次东西,每次买东西会分别带$d[1~4]$个四种面值的硬币,要买的东西总价格为$s$,求每次刚好买下这个东西(即用掉的硬币面值总和恰好为$s$)的方案数。

    【思路分析】

    首先,如果不存在硬币数量的限制,我们很容易想到要用完全背包。于是我们预处理出没有硬币数量限制的情况下,对于每个总价的方案数。

    然后思考如何处理有数量限制的情况,假设只有一种硬币有数量限制,那么强制这种硬币超出限制,此时我们要用其他面值的硬币拼出的价值为$s-(d+1)*c$。因为超出限制,所以显然这些方案是不合法的,方案数为$f[s-(d+1)*c]$。于是我们成功知道了有一种硬币数量超出限制的方案数(此处不保证只有这一种硬币超出限制),用$f[s]$减去所有一种硬币数量超出限制的方案数之后,我们可以想到这其中多减去了两种硬币数量同时超出限制的方案数。到这里是不是有点眼熟?很显然可以发现这题要用容斥解决,所以最后的答案应该为:

    $f[s]-$一种硬币数量超出限制的方案$+$两种硬币数量超出限制的方案$-$三种硬币数量超出限制的方案$+$四种硬币数量超出限制的方案。

    这样就$over$啦!

    【代码实现】

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define g() getchar()
     8 #define rg register
     9 #define go(i,a,b) for(rg int i=a;i<=b;i++)
    10 #define back(i,a,b) for(rg int i=a;i>=b;i--)
    11 #define db double
    12 #define ll long long
    13 #define il inline
    14 #define pf printf
    15 #define mem(a,b) memset(a,b,sizeof(a))
    16 using namespace std;
    17 int fr(){
    18     int w=0,q=1;
    19     char ch=g();
    20     while(ch<'0'||ch>'9'){
    21         if(ch=='-') q=-1;
    22         ch=g();
    23     }
    24     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
    25     return w*q;
    26 }
    27 int c[5],d[5],tot,s;
    28 ll f[100002],ans;
    29 int main(){
    30     //freopen("","r",stdin);
    31     //freopen("","w",stdout);
    32     go(i,1,4) c[i]=fr();tot=fr();
    33     f[0]=1;
    34     go(i,1,4) go(j,c[i],100000) f[j]+=f[j-c[i]];
    35     while(tot--){
    36         ans=0;
    37         go(i,1,4) d[i]=fr();s=fr();
    38         go(i,0,15){//2^4=16
    39             int t=s,type=0;
    40             go(j,1,4) if((i>>(j-1))&1) t-=c[j]*(d[j]+1),type^=1;//容斥的位运算写法
    41             //当前位为1表示强制超出限制            
    42             if(t<0) continue;
    43             if(!type) ans+=f[t];//偶数种硬币超出限制要加上方案
    44             else ans-=f[t];//奇数种硬币超出限制要减去方案
    45         }
    46         pf("%lld
    ",ans);
    47     }
    48     return 0;
    49 }
    代码戳这里
  • 相关阅读:
    flask 日志级别设置只记录error级别及以上的问题
    UnicodeDecodeError: ‘utf-8’ codec can’t decode byte...
    Python 爬虫使用固定代理IP
    python中json报错:json.decoder.JSONDecodeError: Invalid control character at: line 2 column 18 (char 19)
    scrapy中命令介绍
    Python atexit模块
    MP和OMP算法
    如何理解希尔伯特空间
    压缩感知学习博客推荐
    压缩感知系列文章点评
  • 原文地址:https://www.cnblogs.com/THWZF/p/11592759.html
Copyright © 2011-2022 走看看