zoukankan      html  css  js  c++  java
  • HDU4497GCD and LMC最大公约数与最小公倍数

    题目链接

      http://acm.hdu.edu.cn/showproblem.php?pid=4497

    题目大意

      求gcd(x,y,z)=G且lcm(x,y,z)=L的方法数。

    题目分析

      起初这道题一点想法都没有。。看了题解才有些想法。

      首先如果L不能被G整除的话,这样的组合一定不存在。

      当这样的组合存在的时候,所求与  求gcd(x,y,z)=1且lcm(x,y,z)=L/G的方法数是等价的。

      那么:令temp=L/G。

      对temp进行素数分解:temp=p1^t1 * p2^t2 * ……* pn^tn

      因为temp是这三个数的倍数,因而x,y,z的组成形式为:

      x=p1^i1 * p2^i2 *…… * pn^in;

      y=p1^j1 * p2^j2 *…… * pn^jn;

      z=p1^k1 * p2^k2 * …… * pn^kn;

      对于某一个素因子p:

              因为要满足x,y,z的最大公约数为1,即三个数没有共同的素因子,所以min(i,j,k)=0。

              又因为要满足x,y,z的最小公倍数为temp,即p^t必然要至少存在一个,所以max(i,j,k)=t。

              换言之:至少要有一个p^t,以满足lcm的要求;至多有两个包含p,以满足gcd的要求。

              因而基本的组合方式为(0,p^t,p^k),k=0-->t。

              而因为(1,2,3)和(2,1,3)是不同的方法,所有满足要求的方法中,除了(0,0,t)和(0,t,t)各有3种排列之外,其余都有6种排列。

              对于某一个素因子p总的方法数为6*(t-1)+2*3=6*t。

      在根据组合排列的知识,素数与素数之间是分步的关系,因而总的方法数为:6*(t1+t2+……+tn)

      那么这道题另外一个地方就是素因子分解的部分了,详细请见本博POJ1845(http://www.cnblogs.com/xiaozhuyang/p/POJ1845-Sumdiv.html)中的相关知识。

      反过来想,这道题的出发基础是“整数唯一分解定理”,每一个数都能分解成若干个质数相乘的形式。

         

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     int t;
     9     cin>>t;
    10     while(t--)
    11     {
    12         int G,L;
    13         int ti[1000];
    14         cin>>G>>L;
    15         if(L%G)
    16         {
    17             cout<<0<<endl;
    18             continue;
    19         }
    20         int temp=L/G;
    21         int k=0;
    22         for(int i=2;i*i<=temp;)//根号法+奇偶法+递归
    23         {
    24             if(temp%i==0)
    25             {
    26                 ti[k]=0;
    27                 while(temp%i==0)
    28                 {
    29                     ti[k]++;
    30                     temp/=i;
    31                 }
    32                 k++;
    33             }
    34 
    35             if(i==2)
    36                 i++;
    37             else
    38                 i+=2;
    39         }
    40         if(temp!=1)//如果temp本身就是个质数
    41             ti[k++]=1;
    42 
    43         long long ans=1LL;
    44         for(int i=0;i<k;i++)
    45         {
    46             ans*=(6*ti[i]);
    47         }
    48         cout<<ans<<endl;
    49     }
    50     return 0;
    51 }
    HDU4497

     

      

      

  • 相关阅读:
    Regexp:教程
    Regexp:目录
    笔记-C#:C# 方法、属性杂项-01
    Regexp:正则表达式应用——实例应用
    正则表达式:百科
    Regexp:template
    AngularJS:参考手册
    命令目录
    java实现连续数的公倍数
    java实现连续数的公倍数
  • 原文地址:https://www.cnblogs.com/xiaozhuyang/p/HDU4497GCDandLMC.html
Copyright © 2011-2022 走看看