您的位置:首页 > 其它

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
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: