一、题目描述
在一个由1×1的格子组成的平面上,给出两个格子的交点P1(x1,y1)和P2(x2,y2).要求计算出线段P1P2上还有多少格子交点。
二、样例
输入:P1=(1,11),P2=(5,3)
输出:3{(2,9),(3,7),(4,5)}
三、解题思路
先将线段当作向量P1P2将P1移到坐标原点,向量为P1P2={(x2-x1),(y2-y1)},令a=y2-y1,b=x2-x1,c为a和b的最大公约数即c=gcd(a,b),则P1P2={b,a},其斜率为:K=a/b=(a/c)/(b/c),若令a1=a/c,b1=b/c,则a1与b1互质且K=a1/b1.令Qt={t×b1,t×a1} t={1,2,3,4......,c},则Qt是在向量P1P2上的且其也是交点,当t=c时Qt就是P2,所以交点数为c-1即gcd(a,b).
四、辗转相除法
辗转相除法是用来求两个数的最大公约数.
其主要思想: 假设a>b,令a=b×p+q,假设c为a,b的最大公约数即c=gcd(a,b).则有a和b都能整除c.而a=b×p+q,立即推出q也能整除c,故q与b的公约数,但是不是最大公约数呢。这里我们用反证法,假设q与b的最大公约数为c1且c1>c,即gcd(b,q)=c1>c,所以b和q都能整除c1,立即推出a也一定能整除c1,故a与b最大公约数应该大于等于c1,即gcd(a,b)=c>=c1,与c1>c矛盾。故c1=c,
所以得出结论:gcd(a,b)=gcd(b,a%b)且当b=0时有gcd(a,b)=a.
五、最大公约数代码
#include <iostream>
#include <stdio.h>
using namespace std;
int gcd(int a,int b)//求a,b最大公约数
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main()
{
int a,b,c;
scanf("%d,%d",&a,&b);
if(a<=b)//大的放前
c=gcd(a,b);
else
c=gcd(b,a);
printf("%d\n",c);
return 0;
}
六、该题的代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int gcd(int a,int b)//求a,b最大公约数
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main()
{
int a,b,c;
int x1,x2,y1,y2;
scanf("%d%d",&x1,&y1);//输入的一个点
scanf("%d%d",&x2,&y2);//输入的二个点
a=abs(x2-x1);
b=abs(y2-y1);
if(a<=b)//大的放前
c=gcd(a,b);
else
c=gcd(b,a);
printf("%d\n",c-1);
return 0;
}