• 牛客网-小马哥的超级盐水 【折半查找】


    链接: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 如果直接枚举状态肯定超时,但如果枚举 n/2的状态就不会超时,所以可以把n分成两份,分别枚举状态,根据第一份的状态,二分搜索第二份的状态即可。
    状态公式:(ai + aj) / ( bi + bj) = x / y
       => y * (ai + aj) = x * (bi + bj)
       => ai * y - bi * x = bj * x - aj * y

    记录每个状态的 b和 * x - a和 * y就能得出答案。

    附ac代码:
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <vector>
     6 #include <cmath>
     7 #include <string>
     8 using namespace std;
     9 typedef long long ll;
    10 const int maxn = 400000;
    11 ll a[maxn], b[maxn];
    12 ll ansa[maxn], ansb[maxn];
    13 int t;
    14 int n;
    15 ll  x, y;
    16 int lea = 0;
    17 void dfsa(int now, ll sum) {
    18     if(now == n / 2) {
    19         ansa[lea++] = sum;
    20         return;
    21     }
    22     dfsa(now + 1, sum);
    23     dfsa(now + 1, sum + (x * b[now] - y * a[now]));
    24     
    25     return;
    26 }
    27 int leb = 0;
    28 void dfsb(int now,  int sum) {
    29     if(now == n) {
    30         ansb[leb++] = sum;
    31         return;
    32     }
    33     dfsb(now + 1, sum);
    34     dfsb(now + 1, sum + (x * b[now] - y * a[now]));
    35     
    36     return;
    37 }
    38 int main() {
    39 
    40     scanf("%d", &t);
    41     while(t--) {
    42         lea = 0;
    43         leb = 0;
    44         scanf("%d %lld %lld", &n, &x, &y);
    45         for(int i = 0; i < n; ++i) {
    46             scanf("%lld %lld", &a[i], &b[i]);
    47         } 
    48         dfsa(0, ll(0));
    49         dfsb(n / 2, ll(0));
    50     //    printf("%d %d
    ", lea, leb);
    51         ll cnt = 0;
    52         sort(ansb, ansb + leb);
    53         for (int i = 0; i < lea; i++)
    54             cnt += (upper_bound(ansb, ansb + leb, -ansa[i]) - ansb) - (lower_bound(ansb, ansb + leb, -ansa[i]) - ansb);
    55         
    56         printf("%lld
    ", cnt - 1);
    57     }
    58     return 0;
    59 } 
    View Code



  • 相关阅读:
    打开任务管理器的hang住的进程直接右键抓取dmp文件
    Excel匯入匯出整理
    ShellExecute 命令行参数最长2068
    一个判断是否为质数的正则表达式
    visualstudio 比较和merge工具命令行配置
    C++ 螺旋队列
    寻找连通线,参考八后算法递归,可用于验证码去除连续干扰线
    DES 加解密
    记个地址
    CF1383C String Transformation 2 题解
  • 原文地址:https://www.cnblogs.com/zmin/p/8848715.html
Copyright © 2020-2023  润新知