POJ 1061青蛙的约会。求解(x+mT)%L=(y+nT)%L的最小步数T。

 

因为是同余,所以就是(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;
}
View Code

 

★、求解方程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;

 

posted on 2016-08-13 21:58  stupid_one  阅读(315)  评论(0编辑  收藏  举报

导航