又叫辗转相除法,求最大公约数。
时间复杂度在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;
}