HDU5584 LCM Walk(数学+逆向思维)

来源:互联网 发布:类似快快游戏的软件 编辑:程序博客网 时间:2024/06/06 01:17

LCM Walk

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1649    Accepted Submission(s): 851


Problem Description
A frog has just learned some number theory, and can't wait to show his ability to his girlfriend.

Now the frog 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 the frog is sitting at grid (sx,sy), and begins his journey.

To show his girlfriend his talents in math, he uses a special way of jump. If currently the frog 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 jump 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 the frog the number of possible starting grids that can reach (ex,ey)!
 

Input
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.

 1T1000.
 1ex,ey109.
 

Output
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.
 

Sample Input
36 106 82 8
 

Sample Output
Case #1: 1Case #2: 2Case #3: 3
 
题意:给你一个坐标问你满足规则能到达这个点的坐标有几个
规则:对于任意点(x,y)他的前进方式有能向右和向上移动一个lcm(x,y)的距离
也就是说z为x,y的最小公倍数,那下一步是(x+z,y)或(x,y+z),求能到达终点的坐标(ex,ey)的点的数量
思路:对于终点(x,y)来说它的上一点必是由(x,y-z)或(x-z,y)(这里的z为上一点的lcm)所跳得来的,又分析如果终点的y>x,那么上一点必是由(x,y-z)跳到(x,y)
那么我们设终点的上一点为(qt,pt),t为两者的最大公约数,那么lcm(qt,pt)=qpt,所以终点为(qt,pt+qpt)即(qt,pt*(1+q)),也就是说x=qt,y=pt*(1+q)我们对x,y同除与t,那么有
x’=q,y’=p(1+q)
整理一下就是:
满足两个条件即可,对于x,y我们交换两个值使x<y,然后y0=y/t,x0=x/t,对于上一点来说y0/(x0+1)==x0即为合法点,我们从终点逆推
#include<iostream>#include<cstdio>#include<cstring>using namespace std;long long gcd(long long a,long long b){    return b?gcd(b,a%b):a;}int main(){    int t,cas=1;    scanf("%d",&t);    while(t--)    {        long long x,y,cot=1;        scanf("%lld%lld",&x,&y);        printf("Case #%d: ",cas++);        long long d=gcd(x,y);        x/=d;        y/=d;        while(1)        {            if(x>y)            {                long long temp;                temp=x;                x=y;                y=temp;            }            if(y%(x+1))                break;            y/=x+1;            cot++;        }        printf("%lld\n",cot);    }    return 0;}


原创粉丝点击