NEFU 84 五指山

来源:互联网 发布:桥梁建模软件 编辑:程序博客网 时间:2024/04/26 21:06

五指山

Time Limit 1000ms

Memory Limit 65536K

description

西游记中孙吾空大闹天宫,如来佛祖前来降伏他,说道:“我与你打个赌赛;你若有本事,一筋斗打出我这右手掌中,算你赢,再不用动刀兵苦争战,就请玉帝到西方居住,把天宫让你;若不能打出手掌,你还下界为妖,再修几劫,却来争吵。”那大圣闻言,暗笑道:“这如来十分好呆!我老孙一筋斗去十万八千里。他那手掌,方圆不满一尺,如何跳不出去?”急发声道:“既如此说,你可做得主张?”佛祖道:“做得!做得!”伸开右手,却似个荷叶大小。那大圣收了如意棒,抖擞神威,将身一纵,站在佛祖手心里,却道声:“我出去也!”你看他一路云光,无影无形去了。大圣行时,忽见有五根肉红柱子,撑着一股青气。他道:“此间乃尽头路了。这番回去,如来作证,灵霄殿定是我坐也。”翻转筋斗云,径回本处,站在如来掌:“我已去,今来了。你教玉帝让天宫与我。”如来骂道:“你正好不曾离了我掌哩!”大圣道:“你是不知。我去到天尽头,见五根肉红柱,撑着一股青气,我留个记在那里,你敢和我同去看么?”如来道:“不消去,你只自低头看看。”那大圣睁圆火眼金睛,低头看时,原来佛祖右手中指写着“齐天大圣,到此一游。”大圣大吃了一惊道:“有这等事!有这等事!我将此字写在撑天柱子上,如何却在他手指上?莫非有个未卜先知的法术?我决不信!不信!等我再去来!”好大圣,急纵身又要跳出,被佛祖翻掌一扑,把这猴王推出西天门外,将五指化作金、木、水、火、土五座联山,唤名“五行山”,轻轻的把他压住。    我们假设佛祖的手掌是一个圆圈(所以任凭大圣一个筋斗云十万八千里也是飞不出其手掌心),圆圈的长为n,逆时针记为:0,1,2,…,n-1,而大圣每次飞的距离为d.现在大圣所在的位置记为x,而大圣想去的地方在y。现在要你告诉大圣至少要多少筋斗云才能到达目的地。

input

有多组测试数据。第一行是一个正整数T,表示测试数据的组数。每组测试数据包括一行,四个非负整数,n(2 < n < 10^9),表示如来手掌圆圈的长度;d(0 < d < n),筋斗所能飞的距离;x(0<=x< n),大圣的初始位置;y(0 <= y < n),大圣想去的地方。   注意孙悟空的筋斗云只沿着逆时针方向翻。

output

对于每组测试数据,输出一行,给出大圣最少要翻多少个筋斗云才能到达目的地。如果无论翻多少个筋斗云也不能到达,输出“Impossible”.

sample_input

23 2 0 23 2 0 1

sample_output

12

这一题是“青蛙约会”的翻版,出了输入不同以外,其他都不变。(建议大家在做扩展欧几里得时,把方程的变量用三个字母预先存好,然后就不会乱了比如这题中的:a = d;b = n;c = (y-x+n)%n;)


代码如下:

#include<iostream>#include<stdio.h>using namespace std;typedef long long LL;LL gcd(LL a,LL b){    return b==0?a:gcd(b,a%b);}LL exgcd(LL a,LL b,LL &x,LL &y){    if(b==0)    {        x=1;        y=0;        return a;    }    LL g = exgcd(b,a%b,x,y);    LL temp;    temp = x;    x = y;    y = temp - a/b*y;    return g;}int main(){    LL a,b,c,n,d,x,y;    LL xx,yy;    int T;    scanf("%d",&T);    while(T--)    {        scanf("%lld%lld%lld%lld",&n,&d,&x,&y);        a = d;        b = n;        c = (y-x+n)%n;        LL g = gcd(a,b);        if(c%g!=0)        {           printf("Impossible\n");           continue;        }        a = a/g;        b = b/g;        c = c/g;        exgcd(a,b,xx,yy);        LL t = xx*c/b;        xx = xx*c-t*b;        if(xx<0)         xx+=b;        printf("%lld\n",xx);    }    return 0;}

(注:nefu貌似不支持__int64,大家交的时候用long long,还有关于数据类型是long long但是输入却用“%I64d”的同学会WA。)


还有一种比较经典的公式法,代码如下:

#include<stdio.h>#include<iostream>using namespace std;typedef long long LL;LL gcd(LL a,LL b){    return b == 0?a:gcd(b,a%b);}LL exgcd(LL a,LL b,LL &x,LL &y){    if(b == 0)    {        x = 1;        y = 0;        return a;    }    LL g = exgcd(b,a%b,x,y);    LL temp;    temp = x;    x = y;    y = temp - a/b*y;    return g;}int main(){    LL a,b,c,n,d,x,y;    LL xx,yy;    int T;    scanf("%d",&T);    while(T--)    {        scanf("%lld%lld%lld%lld",&n,&d,&x,&y);        a = d;        b = n;        c = (y-x+n)%n;        LL g = gcd(a,b);        if(c % g)        {            printf("Impossible\n");            continue;        }        exgcd(a,b,xx,yy);        xx = (((xx%(b/g)*(c/g)%(b/g)))%(b/g)+(b/g))%(b/g);        yy = (c - a*xx)/b;        printf("%lld\n",xx);    }    return 0;}



0 0