• 30-盐水(分段dfs)


    链接:https://www.nowcoder.com/acm/contest/94/K
    来源:牛客网

    时间限制:C/C++ 5秒,其他语言10秒
    空间限制:C/C++ 131072K,其他语言262144K
    64bit IO Format: %lld

    题目描述

    小马哥有杯盐水,第杯有单位的盐和单位的水。小马哥很无聊,于是他想知道有多少种这杯盐水的非空子集,倒在一起之后盐和水的比是

    输入描述:

    输入第一行包含一个整数,代表数据组数。
    每组数据第一行包含三个整数表示的最大公约数。
    接下来行,第行包含两个整数

    输出描述:

    每组数据输出一行,包含一个整数表示非空子集的个数。
    示例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;
    } 
    

      

     
  • 相关阅读:
    Vue 02
    Vue 初识
    复杂数据类型之函数 对象
    Collections工具类
    遍历集合的方法总结
    使用Iterator迭代器遍历容器元素(List/Set/Map)
    TreeSet的使用和底层实现
    HashSet基本使用
    HashSet底层实现
    TreeMap的使用和底层实现
  • 原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/8858444.html
Copyright © 2020-2023  润新知