• []HAOI2008] 硬币购物 解题报告 ( 完全背包+容斥原理)


    题目链接:https://www.luogu.org/problemnew/show/P1450

    题目描述:

    题解:

    如果去掉限制的话,这就是一个完全背包。

    我们可以考虑先去掉限制,把这个完全背包做出来。

    这个时候我们先考虑一种硬币超出了限制,其他硬币任意的情况。怎么处理成这种情况呢?我们假设当前超过的硬币是i,我们强制用di+1枚硬币,那么剩下的就是一个

    完全背包了,这个完全背包的值就是我们现在算的第i种硬币超了,其他任意的方案数。

    然后我们考虑容斥,第一种第二种都超额、第一种第三种都超额、第一种第四种都超额、第二种第三种都超额、第二种第四种都超额、第三种第四种都超额的方案在上一步中都被减了两次,所以额外都加一次回来,容斥下去就行了

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    
    int tot;
    int c[5],d[5];
    ll f[100050];
    int main()
    {
        for (int i=1;i<=4;i++) scanf("%d",c+i);
        scanf("%d",&tot);
        f[0]=1;
        for (int i=1;i<=4;i++)
            for (int j=c[i];j<=100050;j++) f[j]+=f[j-c[i]];
        while (tot--)
        {
            for (int i=1;i<=4;i++)
            scanf("%d",d+i);
            int s;
            scanf("%d",&s);
            ll res=0;
            for (int i=0;i<15;i++)
            {
                ll t=s;
                int cnt=0;
                for (int j=1;j<=4;j++) if ((i>>(j-1))&1) {t-=c[j]*(d[j]+1);cnt^=1;}
                if (t<0) continue;
                if (!cnt) res+=f[t];else res-=f[t];
            }
            printf("%lld
    ",res);
        }
        return 0;
    }
  • 相关阅读:
    狐狸和兔子
    Arguments to main
    strncpy
    atoi
    sscanf
    集体的智慧:为什么SaaS打败企业软件?
    终于来热风了,又一次感觉到什么叫温暖!
    博士生的毕设
    淡淡的
    endnote如何修改输出格式?
  • 原文地址:https://www.cnblogs.com/xxzh/p/9548878.html
Copyright © 2020-2023  润新知