Gym - 101102A A. Coins 背包问题、数学
2017-01-14 20:56
232 查看
A. Coins
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Hasan and Bahosain want to buy a new video game, they want to share the expenses. Hasan has a set of N coins and Bahosain has a set
of M coins. The video game costs W JDs.
Find the number of ways in which they can pay exactly W JDs such that the difference between what each of them payed doesn’t exceed K.
In other words, find the number of ways in which Hasan can choose a subset of sum S1 and
Bahosain can choose a subset of sum S2such
that S1 + S2 = W and |S1 - S2| ≤ K.
Input
The first line of input contains a single integer T, the number of test cases.
The first line of each test case contains four integers N, M, K and W (1 ≤ N, M ≤ 150) (0 ≤ K ≤ W) (1 ≤ W ≤ 15000),
the number of coins Hasan has, the number of coins Bahosain has, the maximum difference between what each of them will pay, and the cost of the video game, respectively.
The second line contains N space-separated integers, each integer represents the value of one of Hasan’s coins.
The third line contains M space-separated integers, representing the values of Bahosain’s coins.
The values of the coins are between 1 and 100 (inclusive).
Output
For each test case, print the number of ways modulo 109 + 7 on
a single line.
Example
input
output
Source
2016 ACM Amman Collegiate Programming Contest
UESTC 2017 Winter Training #1
Gym - 101102A
My Solution
题意:在a中选一个子集b中选一个子集,使它们的和为w且abs(sumai - sumbi) <= k,问方案数。
背包问题、数学
w = sumai +sumbi,da[j]表示a构出和为j时的方案数,db[j]为构出和为j时的方案数。
故枚举可能的sumai,然后对应w - sumai,则ans = sigma(da[sumai] * db[w - sumai])
然后求da,db的方法是01背包,
复杂度 O(n*w)
Thank you!
------from ProLights
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Hasan and Bahosain want to buy a new video game, they want to share the expenses. Hasan has a set of N coins and Bahosain has a set
of M coins. The video game costs W JDs.
Find the number of ways in which they can pay exactly W JDs such that the difference between what each of them payed doesn’t exceed K.
In other words, find the number of ways in which Hasan can choose a subset of sum S1 and
Bahosain can choose a subset of sum S2such
that S1 + S2 = W and |S1 - S2| ≤ K.
Input
The first line of input contains a single integer T, the number of test cases.
The first line of each test case contains four integers N, M, K and W (1 ≤ N, M ≤ 150) (0 ≤ K ≤ W) (1 ≤ W ≤ 15000),
the number of coins Hasan has, the number of coins Bahosain has, the maximum difference between what each of them will pay, and the cost of the video game, respectively.
The second line contains N space-separated integers, each integer represents the value of one of Hasan’s coins.
The third line contains M space-separated integers, representing the values of Bahosain’s coins.
The values of the coins are between 1 and 100 (inclusive).
Output
For each test case, print the number of ways modulo 109 + 7 on
a single line.
Example
input
2 4 3 5 18 2 3 4 1 10 5 5 2 1 20 20 10 30 50
output
2 0
Source
2016 ACM Amman Collegiate Programming Contest
UESTC 2017 Winter Training #1
Gym - 101102A
My Solution
题意:在a中选一个子集b中选一个子集,使它们的和为w且abs(sumai - sumbi) <= k,问方案数。
背包问题、数学
w = sumai +sumbi,da[j]表示a构出和为j时的方案数,db[j]为构出和为j时的方案数。
故枚举可能的sumai,然后对应w - sumai,则ans = sigma(da[sumai] * db[w - sumai])
然后求da,db的方法是01背包,
复杂度 O(n*w)
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long LL; const int maxn = 1.5e4 + 8; int a[158], b[158]; LL da[maxn], db[maxn], l, r, ans; const LL MOD = 1e9 + 7; inline LL mod(const LL &x) { return x - x / MOD * MOD; } int main() { #ifdef LOCAL freopen("a.txt", "r", stdin); //freopen("a.out", "w", stdout); #endif // LOCAL ios::sync_with_stdio(false); cin.tie(0); int T, n, m, k, w, i, j; cin >> T; while(T--){ memset(da, 0, sizeof da); memset(db, 0, sizeof db); cin >> n >> m >> k >> w; if((w + k) & 1){ l = (w - k) / 2 + 1, r = (w + k) / 2; } else{ l = (w - k) / 2, r = (w + k) / 2; } for(i = 0; i < n; i++){ cin >> a[i]; } da[0] = 1; for(i = 0; i < n; i++){ for(j = w; j >= 0; j--){ if(j - a[i] >= 0) da[j] = mod(da[j] + da[j - a[i]]); else break; } } for(i = 0; i < m; i++){ cin >> b[i]; } db[0] = 1; for(i = 0; i < m; i++){ for(j = w; j >= 0; j--){ if(j - b[i] >= 0) db[j] = mod(db[j] + db[j - b[i]]); else break; } } ans = 0; for(i = l; i <= r; i++){ // cout << da[i] << " " << db[i] << endl; ans = mod(ans + mod(da[i] * db[w - i])); } cout << ans << endl; } return 0; }
Thank you!
------from ProLights
相关文章推荐
- 有趣的数学问题(约瑟夫环+百钱买百鸡+阶梯数+背包问题+欧几里德算法)
- 计算机科学与技术学习心得之计算机理论的一个核心问题--计算数学基础(转载)
- 背包问题另解
- 背包问题的遗传算法解法
- 背包问题
- 动态规划/贪心算法----0/1背包问题AND普通背包问题
- 背包问题经典实现方法
- A*m+B*n=D问题的数学推导求解
- 关于变形的背包问题的答案(C版)
- 三、背包问题
- 希尔伯特的二十三个数学问题
- 如何解决数学软件Maple v9.5在中文Windows下,公式输入中光标定位错误的问题
- 希尔伯特的23个数学问题
- 几个把平面几何问题的辅助线做到空间去的数学趣题
- 数学符号编辑和浏览问题
- 100个经典数学问题
- 数学建模(5)---煤矸石堆积问题
- 1.3.2 0/1背包问题
- 0-1背包问题(回溯法)
- 背包问题