K 小马哥的超级盐水 分治+暴力

本文针对牛客网的一道算法题进行了解析,通过分治思想解决盐水混合后比例为特定值的非空子集数量计算问题。利用dfs遍历和map存储,巧妙处理了比例计算中的加减运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接: 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

2^35次方暴力肯定超时,但是用用分治,将问题1分为2,那么2^17和2^18次方这就不会超时了,题目给了5s。对分成的两部分进行dfs,对于一瓶盐水,都有拿和不拿两个状态,dfs正常思路就可以了 。比较麻烦的是,如何处理x/y的问题,其实这个问题就是将一棵树,分为两颗子树i,j,先对i进行操作,满足ai/bi==x/y 即 ai*y-bi*x==0,这就是满足条件的,而且不满足条件的ai*y-bi*x也要记录下来,因为减法肯定有正有负,因此我们不能用数组,要用map(映射) ,先把所有i树的所有条件都记录下来,那么接下来对j树的处理就是关键了。————大佬教我的!!!

首先我们先看,j树直接符合x/y的,假如说i树有n种,j树有m种,那么单纯符合x/y的组合就有n*m种,但是我们条件不能直接相乘,我们应该用加例如说,对于i树 ,f[0]=3,我们找到一个符合的值那么我们应该用sum+=f[0],如果在找到一个,那么继续sum+=f[0]。

接着,我们看如果两瓶盐水单独不符合,但是混合后符合的情况,i树元素和j树元素如果(ai+aj)/(bi+bj)==x/y 那么我们就有ai*y-bi*x==-aj*y+bj*x ,因此只要满足这个条件我们就可以混合起来,算一种了。也就是说,当求出j树的一个元素为-aj*y+bj*x, 那么f[-aj*y+bj*x]就是找到它对应在i树里混合后等于x/y的值,也就是f[ai*y-bi*x],那么直接sum+=f[-aj*y+bj*x]就可以得到它们总共混合后的种类数,其实也就是相当于上面的n*m。因此j树的边界操作应该是sum+=f[-aj*y+bj*x].

最后一点就是,我们这样做在第i树集合里面我们会有一种情况就是所有水都不取,j树也一样,那么这就是空集了,因此我们算出来的总个数还要-1才是所求的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#define ll long long
using namespace std;
map<ll,ll>f;
int n,m,x,y;
ll a[40],b[40],sum;
void dfs(ll v1,ll v2,int step)
{
    if(step==m)
    {
        f[v1*y-v2*x]++;
        return;
    }
    dfs(v1+a[step],v2+b[step],step+1);
    dfs(v1,v2,step+1);
}
void DFS(ll v1,ll v2,int step)
{
    if(step==n)
    {
        sum+=f[-v1*y+v2*x];
        return;
    }
    DFS(v1+a[step],v2+b[step],step+1);
    DFS(v1,v2,step+1);
}
int main()
{
    int t,i;
    scanf("%d",&t);
    while(t--)
    {
        f.clear();
       sum=0;
        scanf("%d%d%d",&n,&x,&y);
        for(i=0; i<=n-1; i++)
            scanf("%d%d",&a[i],&b[i]);
        m=n/2;
        dfs(0,0,0);
        DFS(0,0,m);
        printf("%lld\n",sum-1);
    }
}



### 小马哥四轴飞行器开源项目代码下载 对于希望获取小马哥开发的小型四轴飞行器相关开源项目的开发者而言,可以通过访问特定平台来找到所需的资源。GitHub是一个广泛使用的托管服务网站,在这里可以发现多个与小马哥有关联的四轴飞行器开源项目[^1]。 具体到小马哥RoboFly以及DragonFly V2这两个基于STM32系列微控制器设计并实现的产品线,其官方团队已经在互联网上公开分享了一些重要的资料和技术文档。例如: - **RoboFly (STM32F103)**: 此版本主要围绕着成本效益较高的STM32F103芯片展开硬件构建工作,并且提供了完整的固件源码供爱好者研究学习。 为了方便用户快速了解和参与到这些有趣的DIY活动中去,除了上述提及的基础文件之外,还额外准备了一系列辅助材料帮助新手入门,比如详细的装配指南、电路原理图说明等[^2]。 如果想要深入探索如何利用Cadence软件套件中的OrCAD Capture CIS工具来进行高效精准的设计,则可以从专门的教学文章中获得指导,这有助于提高个人技能水平的同时也促进了社区内技术交流的良好氛围形成[^3]。 最后值得注意的是,随着时间推移不断有新的改进被加入进来,因此建议定期关注原作者发布的最新动态以便及时掌握最前沿的信息更新情况[^4]。 #### 获取链接 通常情况下,这类开源项目的主页会提供直接指向Git仓库或其他形式存储库位置的超链接按钮;另外也可能存在独立页面用于集中展示所有可用下载项列表。请务必仔细阅读官方网站上的指示文字以确保能够顺利取得所需数据集。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值