首页 > 其他 > 详细

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

时间:2015-07-19 10:21:13      阅读:244      评论:0      收藏:0      [点我收藏+]

题意:链接

方法:容斥原理

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

这题很好想的一个容斥原理,因为一共只有四种硬币,我们不方便计算满足题中要求的方案数,但是从反向思考,我们需要做的就是减掉奇数个硬币用超额的情况,然后加上偶数个硬币用超额的情况就是最终的答案(当然状态是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[N];
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);
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

原文:http://blog.csdn.net/wzq_qwq/article/details/46944777

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!