您的位置:首页 > 其它

BZOJ 1042 [HAOI2008]硬币购物 容斥原理

2015-07-18 19:04 399 查看

题意:链接

方法:容斥原理

解析:简单题,不掉坑都对不起我自己

这题很好想的一个容斥原理,因为一共只有四种硬币,我们不方便计算满足题中要求的方案数,但是从反向思考,我们需要做的就是减掉奇数个硬币用超额的情况,然后加上偶数个硬币用超额的情况就是最终的答案(当然状态是0000的时候看做是一个基准)。

然后我没什么说的了,只是有一些细节需要注意下:

1.要用long long

2.完全背包千万不要傻到每次重新背,直接一次预处理就好,不过我为什么要重新背啊!(差了8s)

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100010
using namespace std;
typedef long long ll;
int c[5],tot;
int d[5],s;
ll f
;
void backpack(int w)
{
    memset(f,0,sizeof(f));
    f[0]=1;
    for(int i=1;i<=4;i++)
    {
        for(int j=c[i];j<=w;j++)
        {
            f[j]+=f[j-c[i]];
        }
    }
}
ll solve()
{
    ll ans=0;
    for(int i=0;i<(1<<4);i++)
    {
        int tmp=s,flag=0;
        for(int j=1;j<=4;j++)
        {
            if(i&(1<<(j-1)))tmp-=(d[j]+1)*c[j],flag^=1;
        }
        if(tmp<0)continue;
        backpack(tmp);
        if(flag)ans-=f[tmp];
        else ans+=f[tmp];
    }
    return ans;
}
int main()
{
    scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&tot);
    while(tot--)
    {
        scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
        ll print=solve();
        if(print<0)printf("0\n");
        else printf("%lld\n",print);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: