码迷,mamicode.com
首页 > 其他好文 > 详细

编程题-线段上格点的个数-最大公约数

时间:2015-02-09 16:09:12      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:最大公约数-最大格点

线段上格点的个数

给定平面上的两个格点P1(x1,y1)P2(x2,y2),线段上P1P2上,除P1P2以外一共有多少格点

虽然可以用穷举法,遍历min(x1,x2)xmax(x1,x2)min(y1,y2)ymax(y1,y2)的格点可以得到正确答案,但是复杂度确实O(|x1?x2|×|y1?y2|),其实这个题的答案是|x1?x2||y1?y2|的最大公约数减去1。(注意,|x1?x2|=0|y1?y2|=0时,答案为0)

原因,首先看一下|x1?x2||y1?y2|的最大公约数代表的是啥? 其实可以看成 在横向和竖向的最大的公共等分数, 比如 6 的等分点可以是 1:1:1:1:1:1分成6份 ,也可以是 2:2:2分成3份,或者是 6,只有1份。(其实对应的是 6能被6,3,1整除) 那么 6和9的最大公共等分数是3,即6分为 2:2:2 , 9分为3:3:3. 那么边长为6和9的矩形,按照这样分会是什么情况呢?
技术分享

通过上图可以看出,大矩形的对角线正好经过 (2,3),(4,6),(6,9) 除开(6,9),就是本体所要求的点。这就是为什么这个题的答案是|x1?x2||y1?y2|的最大公约数减去1。

那这个题可以转换为求最大公约数的问题,最大公约数一般使用辗转相除法

辗转想法的原理:
如果有两个自然数a和b(a>b), 可以写成a=k×b+c
情况1:如果c=0,那么gcd(a,b)=b
情况2:如果c0, 那么gcd(a,b)=gcd(b,c)

下面提供了3个求最大公约数的方法(顺便一提,a和b的最大公倍数为a×bgcd(a,b)

#include <iostream>
#include <cmath> 
using namespace std;
int gcd1(int,int);
int gcd2(int,int);
int gcd3(int,int);
int main(void)
{
    int x1,x2,y1,y2;
    cout<<"input x1,y1,x2,y2"<<endl;
    cin>>x1>>y1>>x2>>y2;
    int abs_x=abs(x1-x2);
    int abs_y=abs(y1-y2);
    int g=gcd3(abs_x,abs_y);
    cout<<g-1<<endl;
    int x_step=(x2-x1)/g;
    int y_step=(y2-y1)/g;
    for(int i=1;i<g;i++)
    {
        cout<<"("<<x1+i*x_step<<","<<y1+i*y_step<<")"<<endl;
    }

}

//非递归的方法 
int gcd1(int a,int b)
{

    int c;
    do
    {
        c=a%b;
        a=b;
        b=c;
    }while(c!=0);   
    return a;
} 

//递归的方法 
int gcd2(int a,int b)
{

    if(b == 0){
        return a;
    }else{
        return gcd2(b,a%b);
    }
} 
//辗转相减法 
int gcd3(int a,int b)
{   
    int c=a-b;
    if(c<0){
        return gcd3(b,a);
    }
    while((a-b)!=0)
    {
        a=a-b;
        if(a<b){
            int tmp=a;
            a=b;
            b=tmp;
        }
    }
    return a;
}

编程题-线段上格点的个数-最大公约数

标签:最大公约数-最大格点

原文地址:http://blog.csdn.net/lizo_is_me/article/details/43670263

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!