2020寒假【gmoj1670】【家庭作业】【最大公因(约)数】

题目描述

Mirko最近收到了一个家庭作业,作业的任务是计算两个数A和B的最大公约数。由于这两个数太大了,我们给出了N个数,他们的乘积是A,给出M个数,他们的乘积是B。

Mirko想要验算自己的答案,所以他想找你写一个程序来解决这个问题。如果这个最大公约数超过了9位数,那么只需要输出最后9位就可以了。

输入

第一行包含一个正整数N,范围是1到1000。第二行是N个用空格隔开的正整数(小于10亿),他们的乘积是A。第三行包含一个正整数M,范围是1到1000。第四行是M个用空格隔开的正整数(小于10亿),他们的乘积是B。

输出

输出有且只有一行,表示A和B的最大公约数,如果结果超过了9位数,输出最后9位数就可以了。
在这里插入图片描述

分析

这题我的第一感觉是用分解质因数的方法做:因为最大公约数就是两个数分别分解质因数然后把相同的质因数乘起来
做完之后发现超时只有40pts。。。

正解:先输入第一个数组,不作处理。
然后输入第二个数组,**输入的每一个都和第一个数组的每一个数做最大公约数。**再用ans乘起来,记得判断如果超过999999999,标记一下,然后mod取最后9位。最后这两个数都要除以它们的最大公约数,避免再用。

最重要的一步:前导0!如果标记了,那就要在这个数前面补上0。先求出这个ans的位数,用ss=9减位数,输出ss个0,最后输出ans。

上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll; 
ll n,m,a[100001],b[100001],ans=1,f,s; 
int zdgys(int x,int y)//辗转相除
{
	int z;
	z=x%y;
	if(z==0) return y;
	else return zdgys(y,z);
}
int main()
{
	freopen("zadaca.in","r",stdin);
	freopen("zadaca.out","w",stdout);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
	}
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>b[i];
		for(int j=1;j<=n;j++)
		{
			s=zdgys(b[i],a[j]);//每个求最大公因数
			ans*=s;//根据题意乘起来(原理)
			if(ans>999999999) //判断位数
			{
				ans%=1000000000;
				f=1;
			}
			b[i]/=s;//除以最大公因数避免重复算
			a[j]/=s;
		}
	}
	if(f==1)//判断标记
	{
		int z,ss=0,q=ans;
		while(q>0)//求位数
		{
			z=q%10;
			ss++;
			q/=10;
		}
		for(int i=1;i<=9-ss;i++)//补0
		{
			cout<<0;
		}
	} 
	cout<<ans;
	fclose(stdin);
	fclose(stdout);
    return 0;
}

发布了63 篇原创文章 · 获赞 61 · 访问量 5427

猜你喜欢

转载自blog.csdn.net/dglyr/article/details/104439738