51 Nod 1256 乘法逆元(数论:拓展欧几里得)

1256 乘法逆元 

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的。

Input

输入2个数M, N中间用空格分隔(1 <= M < N <= 10^9)

Output

输出一个数K,满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的。

Input示例

2 3

Output示例

2

题解:
        对于求最小正K使K*M%N=1,可转换为求m*x+n*y=1的最小正解x;
        需要用到拓展欧几里和定理:
                m*x1+n*y1=1;
                n*x2+(m%n)*y2=1;(m%n=m-m/n*n;)
           =>m*x1+n*y1=m*y2+n*(x2-m/n*y2);
           =>x1=y2,y1=x2-m/n*y2;
           当n=0时可求出x=1;然后往前回溯即可求出结果
           补充:对于求解m*x+n*y=c的解时,若c%gcd(m,n)==0,方程的解将与方程 (m/gcd(m,n))*x + (n/gcd(m,n))*y =c/gcd(m,n) 的相  同。记新方程为a*x + b*y = d,其解将是方程 a*x + b*y = 1的d倍。

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
void gcd(int m,int n,int &x,int &y)
{
        if(n==0){//此时m为初始时m,n的最大公约数1
                x=1;//m*x+n*y=1;m=1,n=0,则x=1;
                y=0;//任意取值
                return ;
        }
        gcd(n,m%n,x,y);
        int tem=x;
        x=y;
        y=tem-(m/n)*y;
}
int main()
{
        int m,n,x,y;
        while(~scanf("%d%d",&m,&n))
        {
                gcd(m,n,x,y);//m*x+n*y=1(m,n互质则gcd(m,n)=1);
                if(x>0)//x>0
                        printf("%d\n",x);
                else//若x<=0,则k要加上m的整数倍(只有这样才能通过改变y的值抵消使右边保持为1)
                        printf("%d\n",n+x%n);
        }
        return 0;
}

 

posted @ 2018-10-23 21:12  aeipyuan  阅读(135)  评论(0编辑  收藏  举报