扩展欧几里得算法的应用-线性同余方程:AcWing 878. 线性同余方程

#include
using namespace std;
typedef long long LL;

int exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    int gcd=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return gcd;
}

int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b,m;
        scanf("%d%d%d",&a,&b,&m);
        int x,y;
        int d=exgcd(a,m,x,y);
        if(b%d) puts("impossible");
        else    printf("%d\n",(LL)b/d*x%m);
    }
    return 0;
}

首先解释一下什么叫做线性同余方程,比如说我们提供一个这样的方程

a*x\equiv b(mod\, m),表示的是\equiv(读作恒等于)左右两边的数字模除m的结果相等。也就是说,存在以下等价关系ax-my=b,-y可以看成另外一个变量y{}',那么就有ax+my{}'=b,然后我们需要判断的就是是否存在一个x和y{}'使得方程有解。经过前面的转换, 就可以直接使用扩展欧几里得算法来进行求解。

扩展欧几里得算法的方程是这样子的:ax+by=gcd(a,b),和我们上面转换得到的方程还是有一些差距,我们把a和m的最大公约数gcd(a,m)记作d,ax+my{}'=b,把这个方程左右两边同时除以\frac{b}{d},变成了,a*\frac{d}{b}x+m\tfrac{d}{b}y{}'=d,然后把\tfrac{d}{b}x\tfrac{d}{b}y{}'看成另外一个变量,然后就完全转换成了扩展欧几里得算法适用的方程。

所以我们根据扩展欧几里得算法算出来的所谓的x其实是前面说的\tfrac{d}{b}x,所以我们输出的时候需要进行这一步操作,

else    printf("%d\n",(LL)b/d*x%m);

注意防止越界,开long long 和取模 

如果b不可以整除d,输出没有整数解,这是为什么?b可以整除d,表示的是,b比d大,并且d是b的因子,d是a和m的最大公约数, (刚开始想错了,条件判断是括号里面只要不是0就表示真,想清楚这个,这个就不需要额外解释说明了)

你可能感兴趣的:(算法竞赛,算法,c++,开发语言,扩展欧几里得算法)