链接:https://www.nowcoder.com/acm/contest/94/K
来源:牛客网
时间限制:C/C++ 5秒,其他语言10秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
小马哥有
杯盐水,第
杯有
单位的盐和
单位的水。小马哥很无聊,于是他想知道有多少种这
杯盐水的非空子集,倒在一起之后盐和水的比是
输入描述:
输入第一行包含一个整数
,代表数据组数。
每组数据第一行包含三个整数%5Cleq%20y%5Cleq10000%2Cgcd(x%2Cy)%3D1))
表示
和
的最大公约数。
接下来
行,第
行包含两个整数%5Cleq%20b_%7Bi%7D%5Cleq%2010000).)
输出描述:
每组数据输出一行,包含一个整数表示非空子集的个数。
示例1
输入
1 5 1 2 1 2 1 2 1 2 1 2 1 4
输出
15
思路:由于n可以为35不能直接深搜,会爆的,所以可以将其分为两部分深搜去求和,又(a1 + a2)/ (b1 + b2) == x / y; 变形为: b1 * x - a1 * y == a2 * y - b2 * x; 可见分为了互不影响的两部分,a1,b1为第一个dfs求和,b2,a2为第二个
dfs求和,最后只有互为相反数即可为一组x/y的组合,同时可以转为map标记。
注意:数据范围。
#include <bits/stdc++.h> using namespace std; map <long long, long long> mp; //要用long long,因为sa = 1e4 * 35, x = 1e4, sa * x < 3e9超int了 long long ans; int a[40], b[40]; int x, y, n; void dfs_before(int k, int sa, int sb){ if(k > n / 2){ mp[x * sb - sa * y]++; return ; } dfs_before(k + 1, sa + a[k], sb + b[k]); dfs_before(k + 1, sa, sb); } void dfs_after(int k, int sa, int sb){ // cout << k << endl; if(k >= n){ ans += mp[sa * y - sb * x]; return ; } dfs_after(k + 1, sa + a[k], sb + b[k]); dfs_after(k + 1, sa, sb); } int main(){ std::ios::sync_with_stdio(false); int t; cin >> t; while(t--){ ans = 0; mp.clear(); cin >> n >> x >> y; for(int i = 0; i < n; i++){ cin >> a[i] >> b[i]; } int m = n / 2; dfs_before(0, 0, 0); dfs_after(m + 1, 0, 0); cout << ans - 1 << endl; //要减去一:sa = sb = 0的情况要除去,虽然符合推导的表达式,但是显然不合题意 } return 0; }