• [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.
  • 相关阅读:
    linux: system calls(系统调用)(rockylinux8.5)
    学习思考:学习模式探究之案例
    cpp:函数返回数组
    shell: list_executable_file 列出当前文件夹的可执行文件名称(linux)
    c_cpp:多级指针
    哲学思考:人类的逻辑
    学习:对学习的深度思考
    Mounting Kubernetes config map as single file returns error: "caused: mount through procfd: not a directory: unknown"
    查看dockerd日志
    kuberneters 实例 CrashLoopBackOff 排查
  • 原文地址:https://www.cnblogs.com/philchieh/p/7476995.html
Copyright © 2020-2023  润新知