XTUOJ ABK(求出A和B的第K大公约数)

Accepted : 21   Submit : 171
Time Limit : 1000 MS   Memory Limit : 65536 KB 

题目描述

ABK是一个比A+B还要简单的题目,给出两个整数A,B,求出A和B的第K大公约数。

输入

第一行是一个整数N(N ≤ 10000),表示样例的个数。 以后每行一个样例,为3个整数A,B,K (1≤A,B≤109 , 1≤K≤10)

输出

每行输出一个整数d,表示A,B的第K大公约数 若没有第K大的公约数则输出-1。

思路:先求出a和b的gcd,a和b的公约数一定也是最大公约数的约数,所以求第K大公约数,可以从1到gcd枚举k个,用gcd除以第k小个约数便是第k大个约数,但是10^9次方的数据量,会T。所以可以从1到根号gcd枚举,假设枚举出n个,如果n>=k便求出,如果n<k,剩下的k-n个必在(gcd-根号gcd)的范围内,不能接着枚举,否则T,要利用好约数的性质,所以仍然可以通过根号gcd到1反向枚举k-n个gcd的约数便求出,复杂度O(根号n)。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<algorithm>
#include<set>
#include<cmath>
#include<vector>
using namespace std;
int a,b,k;
int gcd(int a,int b)
{
    if(b==0)
        return a;
    else
    	return gcd(b,a%b);
}
void solve()
{
    int mx=gcd(a,b),cnt=0;
    for(int i=1;i*i<=mx;i++)                    //正向枚举
    if(mx%i==0){
        cnt++;
        if(cnt==k) cout<<mx/i<<endl;
    }
    for(int i=floor(sqrt(mx)+0.5);i>=1;i--)   //反向枚举//用floor为了避免误差
    if(mx%i==0){
        cnt++;
        if(i*i==mx) cnt--;        //小细节,如果gcd的算数平方根正好是整数,反向枚举的第一个i和正向枚举的最后一个i重复了
        if(cnt==k) cout<<i<<endl;

    }
    if(cnt<k) cout<<"-1"<<endl;
}
int main()
{
   int _;
   cin>>_;
   while(_--)
   {
       cin>>a>>b>>k;
       solve();
   }
   return 0;
}
时间: 2024-10-26 04:42:14

XTUOJ ABK(求出A和B的第K大公约数)的相关文章

最快效率求出乱序数组中第k小的数

题目:以尽量高的效率求出一个乱序数组中按数值顺序的第k 的元素值 思路:这里很容易想到直接排序然后顺序查找,可以使用效率较高的快排,但是它的时间复杂度是O(nlgn),我们这里可以用一种简便的方法,不一定需要排序,使用快速排序中双向分区的扫描方法,扫描出主元下标,然后根据主元的值将数组划分成一半大,一半小.然后再根据主元下标与k进行比较,如果相等,说明主元就是我们要找的数,如果大于k,说明k所代表的值在小的那边,继续向小的那部分递归,如果小于k,说明k代表的值在大的那边,继续向大的那部分递归.这

如果给定参数k,我们想求出所有出现次数超过m/k的元素

http://bar.cnyes.com/html/100102-1/8D260C8C044DB48.shtml http://bar.cnyes.com/html/100102-1/8D260C995AC16FC.shtml http://bar.cnyes.com/html/100102-1/8D260C9B5185528.shtml http://bar.cnyes.com/html/100102-1/8D260C9E4EB206E.shtml http://bar.cnyes.com/h

hdu 1536 S-Nim 博弈论,,求出SG&#39;函数就可以解决

S-Nim Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4975    Accepted Submission(s): 2141 Problem Description Arthur and his sister Caroll have been playing a game called Nim for some time now

c编程:求出4&amp;#215;4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和。

//求出4×4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和 #include <stdio.h> int main() { int sum=0; int max,min; int max1,max2;//记录最大值的坐标 int min1,min2;//记录最小值的坐标 int i,j; int a[4][4]; //为数组赋值 for(i=0;i<4;i++) { for(j=0;j<4;j++) { scanf("%d",&

求出二维数组每一行的平均值

1 //二维数组每行输出平均值 2 //2017.3.7 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 void Rand(int arr[][100], int n); 7 void OutputAvg(int arr[][100], int n); 8 int main() 9 { 10 int arr[100][100]; 11 int n = 10; 12 int sum = 0; 13 //随机初始化数组 14 Rand(a

【c语言】输入一组整数,求出最大子序列的和

// 输入一组整数,求出最大子序列的和. // 例如:序列: - 2 11 - 4 13 - 5 - 2,则最大子序列和为20. // 序列: - 6 2 4 - 7 5 3 2 - 1 6 - 9 10 - 2,则最大子序列和为16 #include <stdio.h> int Max_Son(int *p, int len) { int Max_Sum = 0; int i, j; for (i = 0; i < len; ++i) { int sum = 0; for (j = i

求出数组中所有数字的和&amp;&amp;弹出层效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

欧拉计划013(ProjectEuler013):求出10个数乘积最大的

申明:之前的所有欧拉计划都是用python来写的,的确python来写,代码量极少,学习起来也很方便.但是最近为了找java工作,所以用Java来完成欧拉计划的题,来复习一下Java. Large sum Problem 13 Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. 371072875339021027987979982208375902465101357402

用js写已知abc+cba = 1333,其中a、b、c均为一位数,编程求出满足条件的a、b、c所有组合。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 28.0px Consolas; color: #888471 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 28.0px Consolas; color: #888471; min-height: 33.0px } span.Apple-tab-span { white-space: pre } <!--<script type="text/