zoukankan      html  css  js  c++  java
  • [jzoj]2538.【NOIP2009TG】Hankson 的趣味题

    Link

      https://jzoj.net/senior/#main/show/2538

    Description

      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 的个数。请你帮助他编程求解这个问题。

    Solution

    50分

      显然,答案肯定是最大公约数的倍数,枚举那个数即可。

    100分

      如果存在两个数,a,b,分解质因数得

      a=p1q1*p2q2*p3q3......

      b=pp1qq1*pp2qq2*pp3qq3......

      那么,最大公约数和最小公倍数分别如下。

      gcd(a,b)=p1min(q1,qq1)p2min(q2,qq2)p3min(q3,qq3)......

      lcm(a,b)=p1max(q1,qq1)p2max(q2,qq2)p3max(q3,qq3)......

      我们根据这个关系,将题目所给的lcm,也就是b1分解质因数,根据第二条,我们枚举他每个质因数的指数,判断答案即可。

      注意卡常。

    Code

    {$inline on}
    var
            n,x,i,j,g,a0,a1,b0,b1,now,ans:longint;
            sm:array[1..10,1..2] of longint;
    function gcd(x,y:longint):longint; inline;
    begin
            if x mod y=0 then exit(y);
            exit(gcd(y,x mod y));
    end;
    
    procedure dg(k:longint;ka:int64);
    var
            i:longint;
    begin
            if k>g then
            begin
                    if (gcd(ka,a0)=a1) and (ka div gcd(ka,b0)*b0=b1) then
                            inc(ans);
                    exit;
            end;
    
            for i:=0 to sm[k,2] do
            begin
                    dg(k+1,ka);
                    ka:=ka*sm[k,1];
            end;
    end;
    begin
            readln(n);
            for i:=1 to n do
            begin
                    readln(a0,a1,b0,b1);
                    x:=b1;
                    g:=0;
                    fillchar(sm,sizeof(sm),0);
    
                    for j:=2 to trunc(sqrt(b1)) do
                    begin
                            if x mod j=0 then
                            begin
                                    inc(g);
                                    sm[g,1]:=j;
                                    while x mod j=0 do
                                    begin
                                            x:=x div j;
                                            inc(sm[g,2]);
                                    end;
                                    if x=1 then break;
                            end;
                    end;
    
                    if x>1 then
                    begin
                            inc(g);
                            sm[g,1]:=x;
                            sm[g,2]:=1;
                    end;
                    ans:=0;
    
                    dg(1,1);
    
                    writeln(ans);
            end;
    end.
  • 相关阅读:
    三元表达式、列表推导式、生成器表达式、递归、匿名函数
    nonlocal关键字、装饰器
    函数嵌套、作用域、闭包
    实参和形参
    函数基础
    文件操作
    字符编码
    推荐一个纯JavaScript编写的图表库——Highcharts
    推荐web 前端代码的编辑分享平台——RunJS
    了解腾讯
  • 原文地址:https://www.cnblogs.com/philchieh/p/7476995.html
Copyright © 2011-2022 走看看