zoukankan      html  css  js  c++  java
  • poj 2115 C Looooops(扩展欧几里德)

    呃,整整坐了一天,终于弄懂了这题,同时也弄明白了一个知识点——扩展欧几里德算法,真不容易啊!

    恩,怎么解释呢,从这道题说起吧。

    解这题的思路就是:(a+x*c)%2^k=b,即x*c=(b-a)%2^k。扩展欧几里德算法就是对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,

    y ,使得 gcd(a,b)=ax+by。

    解x,y的方法为:

    1、b=0时,x=1,y=0,gcd(a,b)=a;

    2、a*b<>0时,a*x1+b*y1=gcd(a,b);

    b*x2+(a%b)*y2=gcd(b,a%b);

    根据朴素欧几里德定理知道,gcd(a,b)=gcd(b,a%b);

    即a*x1+b*y1=b*x2+(a%b)*y2=b*x2+(a-(a/b)*b)*y2=b*x2+a*y2-(a/b)*b*y2;

    根据恒等定理解得:x1=y2;y1=x2-(a/b)*y2;然后用递归的形式算出x1,y1的值。

    求解(c*x)%2^k=b,m=2^k,最小的非负整数x;即求解c*x + m*y = b,令c=d1*gcd(c, m),=d2*gcd(c, m)

    所以方程变为 d1 * x + d2 * y = b/ gcd(c,m), 若gcd|b,令d3 = b/gcd(b,m),否则,解不存在。

    d1 * x + d2 * y = d3 ,且gcd(d1, d2)=1

    利用扩展的欧几里得原理求解d1 * x' + d2 * y' = 1

    方程的通解变为 x = x‘ * d3 + d2 * i, y = y’ * d3 - d1 * i。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    long long q,x,y;
    
    void extend_gcd(long long a,long long b)
    {
        if(b==0)
        {
            x=1;y=0;q=a;
        }
        else
        {
            extend_gcd(b,a%b);
            long long tem=x;
            x=y;
            y=tem-(a/b)*y;
        }
    }
    
    __int64 powx(int x)
    {
        __int64 s=1;
        for(int i=1;i<=x;i++)
        s*=2;
        return s;
    }
    
    int main()
    {
        int k;
        long long a,b,c,n,ans;
    
        while (scanf("%lld%lld%lld%d",&a,&b,&c,&k) != EOF)
        {
            if(a==0 && b==0 && c==0 && k==0)
            break;
            if(a==b)
            {
                printf("0\n");
                continue;
            }
            n=powx(k);//注意,这里不能用1<<k来求2^k,当k=31时会出错!
            //printf("%I64d\n",n);
            ans=(b-a+n)%n;
            extend_gcd(c,n);
            //printf("%I64d\n",q);
            if(ans%q)
            printf("FOREVER\n");
            else
            {
                ans/=q;
                c/=q;
                n/=q;
                x*=ans;
                x%=n;
                if(x<0)
                x=(x+n)%n;
                printf("%lld\n",x);
            }
        }
        return 0;
    }

     

  • 相关阅读:
    全局函数和静态函数
    C语言变量总结
    #ifdef、#ifndef 与 #endif
    #include与#define的意义
    exit
    字符常量
    void *:万能指针
    算法(Algorithms)第4版 练习 链表类 1.3.19~1.3.29
    算法(Algorithms)第4版 练习 1.3.219
    算法(Algorithms)第4版 练习 1.3.20
  • 原文地址:https://www.cnblogs.com/misty1/p/2483164.html
Copyright © 2011-2022 走看看