• P1450 [HAOI2008]硬币购物


    传送门

    每种硬币有数量限制,感觉很不好算

    先考虑一下如果没用限制时可以怎么做

    显然直接背包一下就可以了

    设 $f[i][j]$ 表示前 $i$ 种硬币选了一些,总价值为 $j$ 的方案数,转移显然,并且可以滚动数组优化

    但是现在有限制,考虑容斥,设 $f[j]$ 表示不考虑限制总价值为 $j$ 的方案

    一开始答案为 $f[S]$,然后发现多算了,可能硬币不够的方案也算进去了,所有考虑把每一种硬币多出的情况减去,就是强制一种硬币超过限制,其他的顺便选,这个值可以用 $f$ 求出

    然后发现减多了,把两种硬币多出的情况减了 $C^{1}_{2}$ 次 ,把三种硬币多出的情况减了 $C^{1}_{3}$ 次,把四种硬币多出的情况减了 $C^{1}_{4}$ 次

    所以要再把所有两种硬币多出的情况加上来,那么每两种的情况加了 $C^{2}_{2}$ 次,然后每两种硬币多出的情况就刚好只被减了一次

    但是还有点问题,我们又多加了每三种硬币的情况,加了 $C^{2}_{3}$ 次,那么现在三种硬币的情况就没被扣掉

    并且发现四种硬币的情况也被多加了,加了 $C^{2}_{4}$ 次,此时四种硬币超过限制的情况反而多加了 $2$ 次

    先考虑把三种硬币多出的情况扣掉,把每三种硬币的情况减去,

    那么此时每三种硬币的情况刚好被减了 $1$ 次,但是每四种硬币超过限制的情况又被扣了 $C^{3}_{4}$ 次

    此时四种硬币的情况总共被扣了 $2$ 次

    那么最后再把四种硬币的情况加上一次就好了

    总结一下,没有限制 - 一个硬币的限制 + 两个硬币的限制 - 三个硬币的限制 + 四个硬币的限制

    这就是最基础的容斥了,用位运算很方便实现

    具体看代码吧

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e5+7;
    int c[7],d[7],n,m;
    ll f[N],ans;
    int main()
    {
        for(int i=1;i<=4;i++) c[i]=read();
        n=read();
        f[0]=1;
        for(int i=1;i<=4;i++)
            for(int j=c[i];j<N;j++) f[j]+=f[j-c[i]];
        while(n--)
        {
            for(int i=1;i<=4;i++) d[i]=read();
            m=read(); ans=0;
            for(int i=0;i<(1<<4);i++)//枚举硬币的状态,是否强制超过限制
            {
                int cnt=0; ll t=0;//cnt统计一个硬币超过限制,t统计在i状态下最少要多少钱
                for(int j=0;j<4;j++) if((i>>j)&1) cnt++,t+=c[j+1]*(d[j+1]+1);
                if(t<=m)
                    cnt&1 ? ans-=f[m-t] : ans+=f[m-t];//容斥
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    程序员离职躲山洞,2 年敲出 45 万行代码。网友:硅谷精神
    别再自己瞎写工具类了,Spring Boot 内置工具类应有尽有。。。
    使用秘钥登录Linux
    使用cosmos sdk开发公链
    reactnative基本知识点(4/4)
    企业在转型(数字化、变革)中的几个关键点
    yarn: 无法加载文件 C:UsersAdminAppDataRoaming pmyarn.ps1,因为在此系统因为在此系统上禁止运行脚本。
    关于储能技术的几点分析
    MQTT接收字符串(1/2)
    reactnative必备工具(3/4)
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10773808.html
Copyright © 2020-2023  润新知