zoukankan      html  css  js  c++  java
  • 【z12】&&【b092】hankson的趣味问题

    描述
    Hanks 博士是 BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson。现
    在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。
    今天在课堂上,老师讲解了如何求两个正整数 c1和 c2 的最大公约数和最小公倍数。现
    在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公
    倍数”之类问题的“逆问题” ,这个问题是这样的:已知正整数 a0,a1,b0,b1,设某未知正整
    数 x 满足:
    1. x 和 a0 的最大公约数是 a1;
    2. x 和b0 的最小公倍数是 b1。
    Hankson 的“逆问题”就是求出满足条件的正整数 x。但稍加思索之后,他发现这样的
    x 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 x 的个数。请你帮
    助他编程求解这个问题。
    格式
    输入格式

    第一行为一个正整数 n,表示有 n 组输入数据。接下来的 n 行每
    行一组输入数据,为四个正整数 a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入
    数据保证 a0能被 a1 整除,b1 能被 b0整除。
    输出格式

    共n 行。每组输入数据的输出结果占一行,为一个整数。
    对于每组数据:若不存在这样的 x,请输出 0;
    若存在这样的 x,请输出满足条件的 x 的个数;
    样例1
    样例输入1[复制]

    2
    41 1 96 288
    95 1 37 1776
    样例输出1[复制]

    6
    2
    限制
    每个测试点1s

    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=z12

    【题解】

    题目的要求是
    gcd(x,a0)==a1;···①
    lcm(x,b0)==b1;···②
    则根据最大公约数gcd和lcm的关系->q*w/gcd(q,w) == lcm(q,w);
    由①②可得
    gcd(x,a0)==a1;
    gcd(x,b0) == x*b0/b1
    进一步两边同时除右边那个东西
    gcd(x/a1,a0/a1)==1; ···③
    gcd(b1/b0,b1/x)==1; ···④
    而题目限制了a1能整除a0,b0能整除b1;
    而a1<=b1(因为要求x和a0的最大公因数为a1则x>=a1,又x和b0的最小公倍数为a1,所以x<=b1->则a1<=b1);
    所以只要枚举b1的因子x就好;(因为b1/x要为整数);
    然后再看看a1能不能整除x(因为x/a1也要为整数);
    最后再判断③和④是不是成立的;
    写个gcd就好;
    b1的因子的话只要i从1->sqrt(b1)枚举就好;
    然后i是b1的因子的话b1/i也是b1的因子(对称的);
    (要注意x*x的情况,不然会多算);
    数的因子其实没想象的那么多(我记得1e8才100多个的样子);
    所以最后虽然又乘了1000;
    也只是相当于for (i= 1 ->8e7左右);
    外层判断一下i是不是b1的因子;
    但是(进入)for里面做的事情很少;(因子少);
    复杂度也很可观吧.

    【完整代码】

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    int a0,a1,b0,b1,n;
    
    int main()
    {
       // freopen("F:\rush.txt","r",stdin);
        scanf("%d",&n);
        for (int i = 1;i <= n;i++)
        {
            int num = 0;
            scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
            int len = int(sqrt(double(b1)));
            for (int i = 1; i<= len;i++)
                if ((b1%i)==0)
                {
                    int x = i;
                    if ((x%a1)==0)
                        if (__gcd(x/a1,a0/a1)==1 && __gcd(b1/b0,b1/x)==1)
                            num++;
                    x = b1 / x;
                    if (x!= i && (x%a1)==0)
                        if (__gcd(x/a1,a0/a1)==1 && __gcd(b1/b0,b1/x)==1)
                            num++;
                }
            printf("%d
    ",num);
        }
        return 0;
    }
    
  • 相关阅读:
    Snapshot--使用脚本创建快照
    Mirror--日志流压缩
    Mirror--如何TSQL查看镜像状态和镜像相关存储过程
    Mirror--如何对运行中的镜像端点更换证书
    Mirror--程序访问镜像数据库的超时机制
    oozie客户端常用操作命令
    oracle数据库表空间的创建与使用
    Idea创建sbt项目
    Idea配置sbt(window环境)
    使用Idea从github上获取项目
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626969.html
Copyright © 2011-2022 走看看