求最大公约数;
模板:
代码简短,就一行;
主要内容 | 形参 | 返回值 | 主要作用 |
函数gcd() | 两个int类型的形参a,b | int | 返回a,b 的最大公约数 |
int gcd(int a, int b)
{//求a,b的最大公约数
return b ? gcd(b, a % b) : a;//如果b不等于0,求a,b的最大公约数gcd(a,b)==求b,a%b的最大公约数gcd(b,a%b)。如果b等于0的话最大公约数就为a
}
模板题:
给定 n 对正整数 ai,bi,请你求出每对数的最大公约数。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数对 ai,bi。
输出格式
输出共 n 行,每行输出一个整数对的最大公约数。
数据范围
1≤n≤105,
1≤ai,bi≤2×109
输入样例:
2
3 6
4 6
输出样例:
3
2
代码:
#include <iostream>
using namespace std;
const int N=1e5+10;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
int n;
cin>>n;
while(n--){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",gcd(a,b));
}
return 0;
}
例题:
思路:求每个点与源点能构成多少不同的直线,主体是判重。
最关键的一点是有精度问题,因为斜率可以是任何一个数,所以有可能为精度很高的小数,就很难判断直线是否相等。
任意一条直线可以由每个点的坐标与源点构成的向量(x1-x0,y1-y0)确定,设k=gcd(x1-x0,y1-y0),通过储存{ (x1-x0)/k , (y1-y0)/k }确定一条直线。
值得注意的是,向量是有方向的,所以一条直线可以由两个相反的向量确定。
约翰的农场可以看作一个二维平面。
农场中有 n 个老鼠,在毁坏着农田。
第 i 个老鼠的位置坐标为 (xi,yi)。
不同老鼠可能位于同一位置。
在 (x0,y0) 处,装有一个双向发射的激光枪,该位置没有老鼠。
激光枪每次发射都可以将穿过点 (x0,y0) 的某一条直线上的所有老鼠都消灭掉。
请问,为了消灭所有老鼠,至少需要激光枪发射几次。
输入格式
第一行包含三个整数 n,x0,y0,表示共有 n 只老鼠,激光枪的位置为 (x0,y0)。
接下来 n 行,每行包含两个整数 xi,yi,表示第 i 只老鼠的位置为 (xi,yi)。
输出格式
一个整数,表示激光枪的最少发射次数。
数据范围
前 5 个测试点满足 1≤n≤5。
所有测试点满足 1≤n≤1000,−104≤xi,yi≤104。
输入样例1:
4 0 0
1 1
2 2
2 0
-1 -1
输出样例1:
2
输入样例2:
2 1 2
1 1
1 0
输出样例2:
1
代码:
#include <iostream>
#include <set>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N=1010;
set<PII> Anws;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
int n,x0,y0;
scanf("%d%d%d",&n,&x0,&y0);
while(n--){
int a,b;
scanf("%d%d",&a,&b);
a=a-x0,b=b-y0;
if(a<0) a=-a,b=-b;
int k=gcd(a,b);
Anws.insert({a/k,b/k});
}
cout<<Anws.size()<<endl;
return 0;
}