zoukankan      html  css  js  c++  java
  • [HAOI2008]硬币购物-题解

    传送门

    解答

    根据容斥原理

    [left|igcap_{i=1}^n overline{S_i} ight| = |U| - left|igcup_{i=1}^n S_i ight| = sum_{0 le kle n}(-1)^ksum_{1le i_1<cdots<i_kle n}left|igcap_{j=1}^k S_{i_j} ight| ]

    其中(S_i)表示第(i)种元素超限的取的方法集合,交的初始值是(U)。((U)表全集,(overline A)(A)(U)下的补集)

    如何求出(left|igcap_{j=1}^k S_{i_j} ight|)
    考虑先求出完全背包的dp值
    然后强制将第(i_j)个元素选取超过(d_{i_j})个。
    这样的方案总数为(dp[t]-dp[t-sum_{j=1}^k(d_i+1)c_i])。((dp[])的负数项为(0)

    然后就可以愉快地容斥了。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int n = 4, mx = 1e5+10, pm[] = {1,-1};
    #define int long long
    
    int c[n], d[n], dp[mx] = {1};
    
    signed main() {
    	for (int i = 0; i < 4; ++i) {
    		cin >> c[i];
    		for (int j = c[i]; j < mx; ++j)
    			dp[j] += dp[j-c[i]];
    	}
    	int tot, s;
    	cin >> tot;
    	while (tot--) {
    		for (int i = 0; i < 4; ++i) cin >> d[i];
    		cin >> s;
    		int res = 0;
    		for (int i = 0; i < 16; ++i) {
    			int tmp = s, cnt = 0;
    			for (int j = 0; j < 4; ++j) {
    				if ((i>>j) & 1) {
    					cnt++;
    					tmp -= (d[j]+1)*c[j];
    				}
    			}
    //			cout << cnt << ' ' << tmp << endl;
    			res += pm[cnt%2]*(tmp>=0?dp[tmp]:0);
    		}
    		cout << res << endl;
    	}
    }
    
    
  • 相关阅读:
    H3C交换机流量镜像
    脚本引发的思考
    【PAT Advanced Level】1015. Reversible Primes (20)
    JSTL自定义函数完成ACL即时认证
    [翻译Joel On Software]选择一门语言/Choosing a language
    MFC-CWinApp
    poj2462
    HDU 3472 混合图欧拉回路 + 网络流
    Vim命令合集
    Windows下SQLMAP的安装图解
  • 原文地址:https://www.cnblogs.com/topsecret/p/11626423.html
Copyright © 2011-2022 走看看