Revenge of GCD HDU5019

时间:2024-10-09 13:07:03

Description

In mathematics, the greatest common divisor (gcd), also known as the greatest common factor (gcf), highest common factor (hcf), or greatest common measure (gcm), of two or more integers (when at least one of them is not zero), is the largest positive integer that divides the numbers without a remainder.  ---Wikipedia
Today, GCD takes revenge on you. You have to figure out the k-th GCD of X and Y.

Input

The first line contains a single integer T, indicating the number of test cases. 
Each test case only contains three integers X, Y and K. 
[Technical Specification]  1. 1 <= T <= 100 2. 1 <= X, Y, K <= 1 000 000 000 000

Output

For each test case, output the k-th GCD of X and Y. If no such integer exists, output -1.

Sample Input

3 2 3 1 2 3 2 8 16 3

Sample Output

1 -1 2

________________

题意:

给出x , y 求 第k大的公约数(x,y,k <= 1e12)。

看到这题数据范围直接吓尿,一开始写了个 求最大公约数后枚举约数,意料之中的T了。

然后想到,第k大的公约数,其实就是最大公约数的第k个因子。

 如果枚举最大公约数的因子,最大公约数可能有1e12那么大,显然会t.

那么可以考虑只 枚举一半的因子(因为1e12的约数最多 2* sqrt(1e12) 也就是2e6左右( 这里有点问题,我看别人有用1e6存的,我不知道我想的对不对) )

这样,可以用数组存起来,只要

for( int i = 1 ; i <=sqrt( gcd (x,y) ) ; i++)

{

    if( gcd(x,y) % i == 0 )

        array[cnt++] = i ;

    if( gcd (x,y) / i == 0 )

    array[cnt++] = gcd(x,y) / i ;

}

}

然后对这个数组排序后从大到小取就可以了。别人的代码A了自己的T了一下午。

然后又看到别人的思路

先在  1 - sqrt( gcd(x,y) ) 中找,

第n个小的约数所对应的 gcd(x,y) / n 也就是第n个大的约数。

找不到继续在

( gcd(x,y) ) - 1 区间中找 ,找到的也就是第n个大的约数 ( 这里我说不太清楚,不太好理解,大概可以理解为gcd(x,y)先找一边的约数再找另一边)

代码如下:

#include<iostream>

#include<cstdio>

#include<cmath>

#include<algorithm>

using namespace std;

typedef long long int ll ;

ll gcd ( ll a , ll b )

{

        if ( b == 0 ) return a ;

        else

               gcd(b , a % b );

}

int main()

{

        int t ;

        cin>> t;

        for( int z = 1 ; z <= t ; z++)

        {

               llx,y,k;

               cin>> x >> y >> k ;

               llt = gcd(x,y);

               llnum = 0 , v;

               for( int i = 1 ; i <= sqrt(t) ;i++)

               {

                       if( t % i == 0 )

                       {

                               num++;

                               v=t/i;

                       }

                       if( num == k )

                               break ;

               }

               if( num == k )

                       {cout<< v << endl ; continue;}

               else

                       for( int i = sqrt(t) ; i >=1 ; i--)

                       {

                               if( i*i == t)

                                      continue;

                               if( t % i == 0 )

                                      {

                                              num++;

                                              v=i;

                                      }

                               if( num == k)

                                      break ;

                       }

               if( num == k )

                       cout<< v << endl ;

               else cout << "-1" << endl ;

        }

return 0 ; 

}

——————

不知道为什么T了一下午,照猫画虎对着别人思路都T,重新好几次还T。然后晚上饭后一怒之下又重写一遍莫名AC。。

Revenge of GCD HDU5019