欧几里得算法 gcd

本文详细介绍了辗转相除法,又称欧几里得算法,用于求解两个整数的最大公约数。阐述了该算法的时间复杂度,并提供了两种实现方式。通过实例展示了如何使用辗转相除法解决实际问题,如计算线段上的隔点数和寻找与给定整数互素的数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

又叫辗转相除法,求最大公约数。

时间复杂度在O(long max(a,b))内;

核心代码:

int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}

有些地方会卡时,所以另给出一种

ll gcd(ll a,ll b){
//	return b==0?a:gcd(b,a%b);
	if(a==0) return 1;
	if(a<0)	return gcd(-a,b);
	while(b){
		ll t=a%b;
		a=b;
		b=t;
	}
	return a;
}

样例一:

给定平面上的两点p1(x1,y1),p2(x2,y2);线段p1p2上,除p1p2外一个有几个各点:

(枚举很大,所有隔点数=gcd(abs(x1-x2),abs(y1-y2))-1,在 abs(x1-x2)==0&&abs(y1-y2)==0时候要特判);

#include<bits/stdc++.h>
using namespace std;
struct node{
	int x,y;
};
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}
int main(){
	node d1,d2;
	cin>>d1.x>>d1.y>>d2.x>>d2.y;
	if(d1.x-d2.x==0 && d1.y-d2.y==0){
		cout<<0;
		return 0;
	}
	/*int ys=gcd(abs(d1.x-d2.x),abs(d1.y-d2.y));
	int x=abs(d1.x-d2.x)/ys;
	int y=abs(d1.y-d2.y)/ys;
	for(int i=max(d1.x,d2.x);i>min(d1.x,d2.y);i-=x)
	cout<<i<<" ";
	cout<<endl;  
	
	for(int i=min(d1.y,d2.y);i<max(d1.y,d2.y);i+=y)
	cout<<i<<" ";
	cout<<endl; */
	
	cout<<gcd(abs(d1.x-d2.x),abs(d1.y-d2.y))-1;
	return 0;
}

类似的可以求用边长为多少的最小正方形可以无缝隙的填满整个大长方形(a,b);

样例二:poj 2773

考点:1:两个整数最大公约数是1,则这两个正整数是互素的。

           2:与m互素的数对m取模具有周期性:如果小于m且与m互素的数有j个,其中第i个是ai,则第m*j+i个与m互素的数是m*j+ai;

题目要求:对于给出的整数m,找到按升序排列的第k个和m互素的数。

#include<iostream>
using namespace std;
const int maxn=1e6;
int pri[maxn];
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b); 
}
int main(){
	int m,k;
	while(cin>>m>>k){
		int i,j;
		for(i=1,j=0;i<=m;i++)
			if(gcd(m,i)==1)
			pri[j++]=i;
		if(k%j!=0)
			cout<<k/j*m+pri[k%j-1]<<endl;
		else//特判k%j==0
		cout<<(k/j-1)*m+pri[j-1]<<endl;
	}
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值