欧几里德和扩展欧几里德

</pre><pre name="code" class="html">#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=1009;

//欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。
//基本算法:设a=qb+r,其中a,b,q,r都是整数,
//则gcd(a,b)=gcd(b,r),即gcd(a,b)=gcd(b,a%b)。
//递归
int gcd(int a,int b)
 {
     return b ? gcd(b,a%b) : a;
 }
 //非递归
int Gcd(int a, int b)
{
//    while(b!=0)
//    {
//      int r = b;
//      b = a % b;
//      a = r;
//    }
     while(b!=0)
     {
         int r=b;
         b=a%b;
         a=r;
     }
    return a;
}
                      //扩展欧几里德
//基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)
//表示 a,b 的最大公约数,
//必然存在整数对 x,y ,使得 gcd(a,b)=ax+by
int exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int r=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return r;
}
//非递归
int exgcd(int m,int n,int &x,int &y)
{
    int x1,y1,x0,y0;
    x0=1; y0=0;
    x1=0; y1=1;
    x=0; y=1;
    int r=m%n;
    int q=(m-r)/n;
    while(r)
    {
        x=x0-q*x1; y=y0-q*y1;
        x0=x1; y0=y1;
        x1=x; y1=y;
        m=n; n=r; r=m%n;
        q=(m-r)/n;
    }
    return n;
}


//扩展欧几里德算法的应用主要有以下三方面:
//
//(1)求解不定方程;
//
//(2)求解模线性方程(线性同余方程);
//
//(3)求解模的逆元;


//(1)求解不定方程;
bool linear_equation(int a,int b,int c,int &x,int &y)
{
    int d=exgcd(a,b,x,y);
    if(c%d)
        return false;
    int k=c/d;
    x*=k; y*=k;    //求得的只是其中一组解
    return true;
}
//(2)求解模线性方程(线性同余方程);
bool modular_linear_equation(int a,int b,int n)
{
    int x,y,x0,i;
    int d=exgcd(a,n,x,y);
    if(b%d)
        return false;
    x0=x*(b/d)%n;   //特解
    for(i=1;i<d;i++)
        printf("%d\n",(x0+i*(n/d))%n);
    return true;

}
//
//(3)用欧几里德算法求模的逆元:
//
//同余方程ax≡b (mod n),如果 gcd(a,n)== 1,则方程只有唯一解。
//
//在这种情况下,如果 b== 1,同余方程就是 ax=1 (mod n ),gcd(a,n)= 1。
//
//这时称求出的 x 为 a 的对模 n 乘法的逆元。
//
//对于同余方程 ax= 1(mod n ), gcd(a,n)= 1 的求解就是求解方程
//
//ax+ ny= 1,x, y 为整数。这个可用扩展欧几里德算法求出,
//原同余方程的唯一解就是用扩展欧几里德算法得出的 x 。

//模算术

int mul_mod(int a,int b,int n)
{
    return a*b%n;
}

//a的p次方mod n,要求0<=a<n
int pow_mod(int a,int p,int n)
{
    if(p==0)
    return 1;
    int ans=pow_mod(a,p/2,n);
    ans=ans*ans%n;
    if(p%2==1)
    ans=ans*a%n;
    return ans;
}
int main()
{
    int a,b,n;
    while(scanf("%d%d%d",&a,&b,&n)!=EOF)
    {
        int ans=pow_mod(a,b,n);
        printf("%d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值