ACwing算法备战蓝桥杯——Day22——欧几里得算法(辗转相除法)

求最大公约数;

模板:

代码简短,就一行;

主要内容

形参

返回值

主要作用

函数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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

切勿踌躇不前

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值