您的位置:首页 > 其它

[数论]青蛙约会 (扩展欧几里德)

2015-07-31 10:53 381 查看
/*
Name:青蛙约会 (扩展欧几里德)

Actor:HT

Time:2015年7月31日

Error Reporte:

}
*/

#include "stdio.h"
#include "string.h"
#include "iostream"

using namespace std;

int x,y;
//ax+by=gcd(a,b)

int gcd(int a,int b)
{
if (b==0)
{
x = 1;
y = 0;
return a;  //b==0时,gcd(a,0)==a,因此x=1,y=0
}
int d = gcd(b,a%b);
//ax + by =gcd(a,b) = gcd(b,a%b) = b*x0 + a%b*y0 = b*x0 + (a-a/b*b)*y0 = a*y0 + b*(x0-a/b*y0)
//因此  本层的x 等于上一层的y,本层的y 等于上一层的(x-a/b*y)
int temp = x;
x = y;
y = temp - a/b*y;
//debug:printf("%d  %d\n",x,y);
return d;
} //此时的x  y是ax+by=gcd(a,b)的一组特殊解

//扩展欧几里德

//ax + by = gcd(a,b)  ---> (ax + by) * (c/gcd(a,b)) == gcd(a,b) * (c / gcd(a,b))
// ---> 新x = x * (c/gcd(a,b))  新y = y * (c/gcd(a,b))   这是ax+by=c的一组特解

//通解:  X = x + (b/gcd) * T
//    Y = y - (a/gcd) * T

int main()
{
//青蛙约会  x/y    m/n    L
int pa,pb,m,n,l;
int a,b,c,ans;
while(scanf("%d %d %d %d %d",&pa,&pb,&m,&n,&l)!=EOF)
{
//( pa + T*m ) - ( pb + T*n ) == l * K
//(n-m)*T + l*K == pa-pb 注意正负号
a=n-m;
b=l;
c=pa-pb;
int g = gcd(a,b); //此时求得一组特解,但未必最小
if(c%g!=0)   //题意可知,X作为次数T,一定是整数,X=x*(c/g),若c/g非整,X非整,则无解
{
printf("Impossible\n");
continue;
}
x=x*(c/g);
y=y*(c/g);
//当X最小时,由X=x + (b/gcd)*T  当T是使X大于零且最小的值即可
//那么  令X=0,x = (b/gcd)*T   -----> T=x*gcd/b
//※※ps:整型除法--得到的将会是使b/gcd最接近x的T,可能大于可能小于 ,如果大于了,就减去一个b/gcd就好
int t = x*g/b;
ans = x - t*b/g;
if(ans<0) ans+= b/g;
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: