zoukankan      html  css  js  c++  java
  • bzoj1042

    容斥原理+背包

    首先每次做背包是不可行的,那么我们要优化一下,既然是有一些限制条件限制我们获得结果,我们就用容斥去弱化条件,也就是无视一些条件。

    既然硬币是有限制的,那么我们就无视限制,用补集求答案,总方案-超限,但是超限也不好算,就用容斥,先跑完全背包求出总方案,然后减去一个超限,加上两个超限,减去三个超限的,加上四个超限的,这样就计算出了总方案,至于怎么计算超限的方案数,我们只要计算f[s-c[i]*(d[i]+1)],因为这样对应体积的方案数加上c[i]*(d[i]+1)的体积就是强制某种物品超限,但是显然这样是有重复的,容斥解决了这个问题。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    int tot, s;
    long long dp[N];
    int c[5], d[5];
    void ini()
    {
        dp[0] = 1;
        for(int i = 0; i < 4; ++i)
            for(int j = 1; j <= 100000; ++j) if(j >= c[i])
                dp[j] += dp[j - c[i]];
    }
    int main()
    {
        for(int i = 0; i < 4; ++i) scanf("%d", &c[i]);
        scanf("%d", &tot);
        ini();
        while(tot--)
        {
            for(int i = 0; i < 4; ++i) scanf("%d", &d[i]);
            scanf("%d", &s);
            long long ans = 0;
            for(int i = 0; i < (1 << 4); ++i)
            {
                int t = __builtin_popcount(i) % 2 == 0 ? 1 : -1, sum = s;
                for(int j = 0; j < 4; ++j) if(i & (1 << j))
                    sum -= c[j] * (d[j] + 1);
                ans += sum >= 0 ? (long long)t * dp[sum] : 0;                    
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python 正则表达式
    Python 集合
    Python 类的使用
    Python 分支、循环语句
    Python 基础之字典(dict)的用法
    Python 之字符串常用操作
    python tuple元组操作
    Python list的常用操作
    appium 二次切换webview后无法找到页面元素
    Locust API 文档
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7414003.html
Copyright © 2011-2022 走看看