bzoj1477: 青蛙的约会

传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1477

思路:扩展欧几里德求解同余方程。

设x步后碰面,初始位置为x0,y0。

那么就有x0+mx=y0+nx(mod L)

(m-n)x=y0-x0(mod L) //程序里要先把m-n变成正数,L已经是正数,不用变,负数模会有问题,这两步的等号是同余。

于是就可以把这个同余方程变为不定方程ax+by=c

 (m-n+L*t)x+Ly=(y0-x0) modL

然后就是exgcd的事了。


exgcd是用来求ax+by=Gcd(a,b)的整数解的

借用gcd的思想

bx'+(a%b)y'=gcd(b,a%b)

只要把这个方程化为上一个方程的形式,那么我们就可以由下一层推出这一层的解。

于是有bx'+(a-(a/b)*b)y'=gcd(b,a%b)

ay'+b(x'-(a/b)y')=gcd(b,a%b)

gcd(b,a%b)=gcd(a,b)

所以x=y',y=(x'-(a/b)y')

递归的底层即当b=0时,显然,x=1,y=0是一组解。

于是我们就可以层层向上求出一组解


对于ax+by=c的求解可以先求出ax+by=gcd(a,b),然后将x,y扩大c/gcd(a,b)倍就可以了。

无解(整数解)就是c%gcd(a,b)!=0,

当Gcd(a,b)=1时//没有这个就会漏解

通解即为 x=x0+bt

    y=y0-at

于是就可以求最小整数解之类的问题了


对于这道题,只要求出 (m-n+L*t)x+Ly=(y0-x0) mod L的最小整数解即可

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll x0,y0,m,n,L;

ll exgcd(ll a,ll b,ll &x,ll &y){
	if (b==0){x=1,y=0;return a;}
	int Z=exgcd(b,a%b,x,y),t=x;
	x=y,y=t-a/b*y;return Z;
}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}

int main(){
	scanf("%lld%lld%lld%lld%lld",&x0,&y0,&m,&n,&L);
	ll A=((m-n)%L+L)%L,B=L,C=y0-x0,x,y,t=exgcd(A,B,x,y);
	if (C%t!=0){puts("Impossible");return 0;}
	A/=t,B/=t,C/=t,x=(x*C%B+B)%B;
	printf("%lld\n",x);
	return 0;
}



posted @ 2015-10-11 10:32  orzpps  阅读(181)  评论(0编辑  收藏  举报