您的位置:首页 > 其它

HHUOJ 1022 LCM and Walk(数学规律)

2016-09-08 00:41 288 查看

问题 D: LCM and Walk

时间限制: 1 Sec  内存限制: 128 MB
提交: 4  解决: 2

题目描述

Jerry has just learned some number theory, and can't wait to show his ability to Tom.

Now Jerry is sitting on a grid map of infinite rows and columns. Rows are numbered 1,2,⋯ from the bottom, so are the columns. At first Jerry is standing at grid (sx,sy), and begins his journey.

To show Tom his talents in math, he uses a special way of walk. If currently Jerry is at the grid (x,y), first of all, he will find the minimum z that can be divided by both x and y, and walk exactly z steps to the up, or to the right. So the next possible
grid will be (x+z,y), or (x,y+z).

After a finite number of steps (perhaps zero), he finally finishes at grid (ex,ey). However, he is too tired and he forgets the position of his starting grid!

It will be too stupid to check each grid one by one, so please tell Jerry the number of possible starting grids that can reach (ex,ey)!

输入

First line contains an integer T, which indicates the number of test cases.

Every test case contains two integers ex and ey, which is the destination grid.

⋅ 1≤T≤1000.

⋅ 1≤ex,ey≤109.

输出

For every test case, you should output "Case #x: y", where x indicates the case number and counts from 1 and y is the number of possible starting grids.

样例输入

3
6 10
6 8
2 8

样例输出

Case #1: 1
Case #2: 2
Case #3: 3


思路:

规定这样一个运算,它从起点(x,y)出发,每次它会走LCM(x,y)步[LCM(x,y)就是x,y的最小公倍数]到达点(x+LCM(x,y),y)或点(x,y+LCM(x,y)),最终,它会到达点(ex,ey),现给你终点(ex,ey),要你求出它的起点有多少种可能。先顺推,看它走到一个点是怎么走到的。因为两个数一定有最小公倍数,所以不如把最初始的起点的两个数看作因数分解的形式。然后每次都有两种选择,先把它们写出来,会发现:1、每次两个数里面都会有k这个因子;2、还会出现较小的数+1这个因子。所以说,如果(ex,ey)这个点是可以走到的,那么它一定会满足1和2两个性质。所以倒推,每次都判断1、2性质是否成立,如果都成立那么可达,如果不成立就说明到这步就停止了。如果纵坐标比横坐标大,那么一定是纵坐标进行了增加变换,那么你判断完符合1、2性质之后就要把纵坐标除以横坐标+1来进行下一次判断,,如果横坐标比纵坐标大也是这个道理。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}

int main()
{
// freopen("in.txt","r",stdin);
int t,ans=1,x,y;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&x,&y);
printf("Case #%d: ",ans++);
int num=1;
int fac = gcd(x,y);
while( 1 ){
if( x < y ){
int m1 = x / fac;
int m2 = y / fac;
if( m2%(1+m1) == 0 )
num++;
else break;
y = m2/(1+m1)*fac;
}
else{
int m2 = y / fac;
int m1 = x / fac;
if( m1%(m2+1) == 0 )
num++;
else break;
x = m1/(1+m2)*fac;
}
}
printf("%d\n",num);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: