POJ 2115 C Looooops 扩展gcd的应用 及其 gcd exgcd的讲解

点击打开链接


题意
1 .对于C的for(i=A ; i!=B ;i +=C)循环语句,问在k位存储系统中循环几次才会结束。

    若在有限次内结束,则输出循环次数。

    否则输出死循环。
思路:
    2 扩展欧几里德算法源于欧几里德算法。
欧几里德算法:gcd(a,b)= gcd(b,a%b)。

证明:a可以表示成a = kb + r,则r = a mod b  

          假设d是a,b的一个公约数,则有d|a, d|b,

          而r = a - kb,因此d|r  因此d是(b,a mod b)的公约数  

          假设d 是(b,a mod b)的公约数,则d | b , d |r ,但是a = kb +r  

          因此d也是(a,b)的公约数  

          因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证

3 拓展欧几里德是用来求二元一次不定方程a*x+b*y=gcd(a,b),---我们这样想 对于a'=b, b'=a%b=a-(a/b*b),

 a*x+b*y=gcd(a,b)

a'*x0+b'*y0=gcd(a',b')=gcd(a,b)=a*x+b*y

b*x0+(a-a/b*b)y0=a*x+b*y

a*y0+b*(x0-a/b*y0)=a*x+b*y

所以:  x=y0   ; y=x0-a/b*y0

4 若我们已经求得x0,y0为方程中x的一组特解,那么

x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t(t为任意整数)也为方程的解
                                      
x=1,y=0,因为最后是求方程a*x+0*y=a(gcd(a,0)==a),此时只要满足a=1,
y为任意值就行,对于每一个y值,最后求出的都是方程的一组解。


5 更通常的是:我们需要求解方程的最小整数解

若我们已经求得x0,y0为方程中x的一组特解,那么

x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t(t为任意整数)也为方程的解

且b/gcd(a,b),a/gcd(a,b)分别为x,y的解的最小间距
,所以x在0~b/gcd(a,b)区间有且仅有一个解,

同理y在0~a/gcd(a,b)同样有且仅有一个解,这个解即为我们所需求的最小正整数解。
        
        
6 本题 :
    n=2^k;
    ///t为 t次重复
    x=([(B-A)+t*n]% n)/C;  ///整除得到 x
    x*C= (B-A) (mod n);   ///模线性方程组
    a=C ;
    b=B-A;
    a*x=b (mod n);
    =>    所以a*x -b 是m的整数倍
=>   a*x-n*y=b  ;

代入 扩展  gcd即可

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define LL long long
using namespace std;
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(b==0)
    {
        x=1;y=0;
        d=a;
        return ;
    }
    exgcd(b,a%b,d,x,y);
    int t=x;
    x=y;
    y=t-(a/b)*y;
}
int main()
{
   LL A,B,C,D;
    while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&D))
    {
        if(!A&&!B&&!C&&!D)
            break;
       LL d,x,y;
        LL a=C,b=B-A;
        
        LL n=((LL)1)<<D;
        exgcd(a,n,d,x,y); 
        
        if(b%d!=0)           ///方程 ax=b(mod n)无解
            printf("FOREVER\n");
        else
        {
            x=(x*(b)/d)%n;        ///方程右边值比
            x=(x%(n/d)+n/d)%(n/d);    ///方程ax=b(mod n)的最小整数解
             printf("%lld\n",x);
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值