51nod-1179 最大的最大公约数

44 篇文章 0 订阅

题目来源:  SGU
基准时间限制:1 秒 空间限制:131072 KB 分值: 40  难度:4级算法题
 收藏
 关注
给出N个正整数,找出N个数两两之间最大公约数的最大值。例如:N = 4,4个数为:9 15 25 16,两两之间最大公约数的最大值是15同25的最大公约数5。
Input
第1行:一个数N,表示输入正整数的数量。(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应输入的正整数.(1 <= S[i] <= 1000000)
Output
输出两两之间最大公约数的最大值。
Input示例
4
9
15
25
16
Output示例
5

思路:

一,对于最大公约数一定在 1-Max(数组最大值)中,因此可以由大到小遍历GCD,对于 GCD只要查找它的倍数是否存在两个即可。

二,求出数组所有元素的全部约数,对于每个元素,可利用约数定理来求解。

Code 1 :

#include<iostream>
using namespace std;

const int MAX_S=1000005;
int n;
int a[MAX_S];

int main()
{
	ios::sync_with_stdio(false); 
	cin>>n;
	int Max=0;
	for(int i=0,x;i<n;++i)
	{
		cin>>x;
		Max=max(Max,x);
		a[x]=1;
	}
	int ans=-1;
	for(int i=Max;i>=0&&ans==-1;--i)	//O(nlog(n))
		for(int j=i,t=0;j<=Max;j+=i)
		{
			t+=a[j];
			if(t>=2){
				ans=i;	break; 
			}	
		}
	cout<<ans<<endl;
	return 0;
}

Code 2 :

#include<iostream>
#include<cmath>
#include<map>
using namespace std;

const int MAX_S=1000005;
const int prime[205]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,
107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,
251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,
409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,
577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,
743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,
929,937,941,947,953,967,971,977,983,991,997,}; //168
int n;
int d[MAX_S];
map<int,int> imap;

void f(map<int,int>::iterator t,int p);
int main()
{
	ios::sync_with_stdio(false);
	cin>>n;
	int Max=0;
	for(int i=0,x;i<n;++i)
	{
		cin>>x;
		Max=max(Max,x);
//		for(int j=sqrt(x);j<=x;++j) //TEL
//			if(x%j==0){
//				d[x/j]++;	d[j]++;
//			}
		imap.clear();
		for(int i=0;i<168;++i)
		{
			while(x%prime[i]==0){
				x/=prime[i];
				imap[prime[i]]++;
			}
			if(x<prime[i])	break;
		}
		if(x!=1)	imap[x]++;
		f(imap.begin(),1);
	}
	int ans=0;
	for(int i=Max;i>=0;--i)
		if(d[i]>=2){
			ans=i;	break; 
		}
	cout<<ans<<endl;
	return 0;
}

void f(map<int,int>::iterator t,int p)
{
	if(t==imap.end()){
		d[p]++;	return;
	}
	int aa=t->first,bb=t->second;
	map<int,int>::iterator ti=t;
	++ti;
	for(int i=0,pi=1;i<=bb;pi*=aa,++i)
		f(ti,p*pi);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值