标签:
因为是同余,所以就是(x+mT)%L-(y+nT)%L=0。可以写成(x-y+(m-n)T)%L=0。就是这个数是L的倍数啦。那么我可以这样x-y+(m-n)T + Ls = 0。就可以了,s可正可负,就能满足条件。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> LL gcd(LL n,LL m) { if (n%m==0) return m; else return gcd(m,n%m); } LL exgcd (LL a,LL mod,LL &x,LL &y) { //求解a关于mod的逆元 if (mod==0) { x=1;y=0; return a;//保留基本功能,返回最大公约数 } LL g=exgcd(mod,a%mod,x,y); LL t=x; //这里根据mod==0 return回来后, x=y; //x,y是最新的值x2,y2,改变一下,这样赋值就是为了x1=y2 y=t-(a/mod)*y; // y1=x2(变成了t)-[a/mod]y2; return g; //保留基本功能,返回最大公约数 } LL get_min_number (LL a,LL b,LL c,LL &x,LL &y) { //得到a*x+b*y=c的最小整数解 LL abGCD = gcd(a,b);//系统gcd if (c%abGCD != 0) return -1;//无解 a /= abGCD; b /= abGCD; c /= abGCD; LL tx,ty; exgcd(a,b,tx,ty); //先得到a*x+b*y=1的解,注意这个时候gcd(a,b)=1 x = tx*c; y = c*ty;//任意一个解,就是因为你求的是a*x+b*y=1的解,但是我们需要的是a*x+b*y=c的解,所以同时乘上c //然后这个方程的解就是x0=tx*c+b*k,y0=ty*c-a*k。这里的a和b约简了的。k是{-1,-2,0,1,2}等 LL temp_x = x; x %= b; if (x<=0) x += b;//最小解 LL k = (temp_x-x)/b; y += k*a; return 1;//1代表可以 } void work () { LL x,y,n,m,L; cin>>x>>y>>m>>n>>L; LL a=m-n; LL b=L; LL c=y-x; LL tx,ty; LL t = get_min_number(a,b,c,tx,ty); if (t==-1) { cout<<"Impossible"<<endl; return ; } if (b<0) b=-b; while(tx<0) tx += b; cout<<tx<<endl; return ; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif work(); return 0; }
★、求解方程ax+by=c的最小整数解 (a或者b是负数的话,直接放进去也没问题)
首先就是如果要求解ax+by=c的话,用exgcd可以求到ax+by=1的x,y。那么我们首先把a和b约成互质的(除以gcd(a,b)即可),求到Ax+By=1的x和y后,但是我们要的是Ax+By=C的解,所以同时乘上C,这里的大写的字母是代表约去gcd(a,b)后的方程。然后这个方程的解就是x0=tx*C+B*k。y0=ty*C-A*k。k是{-1,-2,0,1,2}等。
int get_min_number (int a,int b,int c,int &x,int &y) //得到a*x+b*y=c的最小整数解
{
int abGCD = gcd(a,b);
if (c%abGCD != 0) return -1;//无解
a /= abGCD; b /= abGCD; c /= abGCD;
int tx,ty;
exgcd(a,b,tx,ty); //先得到a*x+b*y=1的解,注意这个时候gcd(a,b)=1
x = tx*c; y = c*ty; //同时乘上c,c是约简了的
int temp_x = x;
x %= b; if (x<=0) x += b;//最小解
int k = (temp_x-x)/b;
y += k*a;
return 1;//1代表可以
}
若要得到最小的正整数解。注意这里要先判定他们是否存在解,不然TLE。
int bb=abs(b/gcd(a,b));
int aa=abs(a/gcd(a,b));
while(x<0) x += bb;
while(x*a+b*y!=c) y += aa;
POJ 1061青蛙的约会。求解(x+mT)%L=(y+nT)%L的最小步数T。
标签:
原文地址:http://www.cnblogs.com/liuweimingcprogram/p/5768990.html