声网09-15,求1-n的最大公约数
今天声网25个选择+2编程题,题目全是英文,这道题是第二题。
题目描述大致是输入T组数据,每一组是一个数字n,输出每一个数n其从1到n的最大公约数gcd最大值,举个例子,求3的gcd最大值,也就是求gcd(1,2),gcd(1,3),gcd(2,3)的最大值
输入形式:
2
3
5
输出形式:
1
2
思路:
首先想到的是暴力做法,定义一个求最大公约数的函数,然后针对每一个数用双指针两层遍历循环求gcd,然后保存其最大值,但是提交不通过显示超时(当时数据规模记不得了,应该是10^6,双层循环肯定要超),代码如下:
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b){
int t;
while(b>0){
t = a%b;
a = b;
b = t;
}
return a;
}
int main(){
int T;
cin>>T;
vector<int> res;
for(int i = 0;i<T;i++){
int x,Max=-1;
cin>>x;
for(int j = 1;j<x;j++){
for(int k = j+1;k<=x;k++){
int res = gcd(j,k);
Max = Max>res?Max:res;
}
}
res.push_back(Max);
}
for_each(res.begin(),res.end(),[](int n){cout<<n<<endl;});
return 0;
}
后来就想着怎么优化,怎么都想不出来暴力做法如何去进行优化,后来换个思路去想。
想到我们完全可以不用求最大公约数的函数,我们可以对所有可能的最大公约数进行遍历除,根据除出来的答案是否大于1去求解。因为n凡是能被2整除且结果大于1,那么他的公约数最小就是2,我们可以从2~n一直遍历求解,这样就能求出最大公约数了。
比如求5,因为5/1=5,5/2=2,5/3=1,5/4=1,5/5=1,那么此时除数2所对应的答案是最大值,所以2就是我们所求。
#include<bits/stdc++.h>
using namespace std;
int main(){
int T;
cin>>T;
vector<int> res;
for(int i = 0;i<T;i++){
int x,Max=-1;
cin>>x;
for(int j = 1;j<=x;j++){
if(x/j>1) Max = j;
else break;
}
res.push_back(Max);
}
for_each(res.begin(),res.end(),[](int n){cout<<n<<endl;});
return 0;
}
拓展:
求最大公约数和最小公倍数的递归形式
//最大公约数
int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
//最小公倍数
int gbs(int x,int y){
return x/gcd(x,y)*y;//用到gcd
}