51nod: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*M%N=1等价于K*M=1+N*X等价于K*M-X*N=1,这种形式就是不定方程x*m+y*n=gcd(m,n)的形式,这里m和n给出来了,且互质
,所以gcd(m,n)=1,然后用exgcd求解不定方程即可。

怎么求呢?我也是第一次学习,感觉这个博主写的不错,传送

我再拷贝下在这里,以便记住推导过程:

//小小地讲一下exgcd球不定方程原理 
 对于ax+by=gcd(a,b);  
我们设一下a>b,在简单直接把b=0时,gcd(a,b)=a.此时,x=1,y=0;  
接着,a>b>0,我们这里可以摆两个式子:①:ax1+by1=gcd(a,b);继续,②:bx2+(a mod b)y2=gcd( b , a mod b );第二个式子为何呢?这就是gcd的辗转相除法的算法啊。而且
gcd(a,b)=gcd(b,a mod b);  
然后我们就能将gcd左边两个等式列个等式:ax1+by1=bx2+(a mod b)y2;额。。。a mod b可以写成?a-(a/b)b对吧,
那么等式变成ax1+ by1= bx2+ (a - (a / b) * b)y2=bx2+ay2 - (a / b)by2 ;我们把ax1+ by1=bx2+ay2 - (a / b)by2拎出来,整理一下,写成:ax1+by1=ay2+b(x2-(a/b)y2); 那么很明显我
们可以得到,x1=y2,y1=x2-(a/b)y2;  
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2. 


代码如下:
#include 
typedef long long LL;
LL m,n,k,x;
void exgcd(LL a,LL b)
{
	if(b==0)//递归结束的终止条件 
    {
        k=1;
        x=0;
        return;
    }
    exgcd(b,a%b);
    LL temp=k;
    k=x;//相当于x1=y2 
    x=temp-(a/b)*x;//相当于y1=x2-(a/b)*y2 
}
int main()
{
	scanf("%lld%lld",&m,&n);
	exgcd(m,n);
	while(k<0)//所求出来的解可能是负的,题目说要最小的正数解,这样循环把他弄成正数 
	{
		k=(k+n)%n;
	}
	printf("%lld\n",k);
	return 0;
} 

你可能感兴趣的:(数学,exgcd)