• 扩展的欧几里得&中国剩余定理


    扩展的欧几里得(EXTENDED-EUCLID)

    一、假设:
         对于给定的整数a和b,它们满足方程:ax+by=d=gcd(a,b),求出整系数x,y

    二、推理:

        ax+by=gcd(a,b)=gcd(b,a%b)=bx+(a-(int)a/b*b)y=ay+b(x-(a-(int)a/b*y)


    三、扩展的欧几里得算法:
     1 int extended_gcd(int a, int b, int &x, int &y)
    2 {
    3 int ret, tmp;
    4 if (!b) {
    5 x = 1; y = 0; return a;
    6 }
    7 ret = extended_gcd(b, a % b, x, y);
    8 tmp = x;
    9 x = y;
    10 y = tmp - a / b * y;
    11 return ret;
    12 }

    四、应用:
         1、求解模线性方程:ax≡b (mod n)
            定理一:设d=gcd(a,n),用扩展欧几里得算法解线性方程 ax'+ny'=d.如果d|b,则方程axºb(mod n)有一个解的值x0=x'(b/d)mod n
            定理二:方程axºb(mod n)有解(即存在d|b,其中d=gcd(a,n)),x0是该方程的任意一个解,则该方程对模n恰有d个不同的解,分别为
                         x(i)=x(0)+i(n/d)(i=1,2,...d-1)
            
             //用扩展欧几里得解模线性方程ax=b (mod n)
          
    bool modularLinearEquation(int a,int b,int n)
    {
    int x,y,x0,i;
    int d=Extended_Euclid(a,n,x,y); //ax=b (mod n) 等价于ax+ny=b
    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;
    }


         2、求乘法逆元:ax≡1(mod n)
              ax≡1(mod n)等价于 ax+ny=1=gcd(a,n),调用extended_gcd(a,n,x,y),并当公约数ret=1(a,n互为质数,ret一定等于1)时,
              当x>0时,x即为a的乘法逆元。当x<0时,将x转换为mod n的最小正整数即可:
        while(x<0)
          x+=n;
         注:Java中没有指针,不能向C/C++这样调用;而C/C++可以使用指针或引用传出形参x,这个特性,使C/C++函数能返回多个值,而
         Java方法最多只能返回一个值。那么在Java版本的实现中,可以将这里的x定义为一个类变量(static),这样就可以获取x的值了。
     
     
    中国剩余定理(CRT)
     
    一、 背景介绍:
         在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),
    问物几何?”这个问题称为“孙子问题”,该问题的一般解法国际上称为“中国剩余定理”。具体解法分三步:
    1、找出三个数:从3和5的公倍数中找出被7除余1的最小数15,从3和7的公倍数中找出被5除余1 的最小数21,最后从5和7的公倍数中找出除3余1的最小数70。
    2、用15乘以2(2为最终结果除以7的余数),用21乘以3(3为最终结果除以5的余数),同理,用70乘以2(2为最终结果除以3的余数),然后把三个乘积相
         加(15*2+21*3+70*2)得到和233。
    3、用233除以3,5,7三个数的最小公倍数105,得到余数23,即233%105=23。这个余数23就是符合条件的最小数。
         
    二、 形式化解释:
                假设x是那个未知数,而除3,5,7后的余数分别为r1,r2,r3。因此有 
                   x≡r1(mod 3) 
                   x≡r2(mod 5) 
                   x≡r3(mod 7) 
     
               第一步:就是找除了r[i]之外的所有余数r[j](j≠i)的乘积(最小公倍数);
               第二步:在求n1,n2,n3时又用了一个小技巧,以n1为例,并非从5和7的公倍数中直接找一个除以3余2的数,而是先找一个除以3余1的数,再乘以2。
                        (定理:如果 a%b=c,那么 (a*k)%b=kc (k为大于零的整数))
              第三步:n1+n2+n3只是问题的一个解,并不是最小的解,故最小解应是该解的等价类。
              注:中国剩余定理的思想在于先找到一个满足条件的数,不管是不是最小的,如果不是最小的就不断减公倍数,中国剩余定理的巧妙在于把满足条件的数
                        分成三个部分相加。
     
    三、典型问题:输入b[i],r[i](分别为除数和余数)求a(被除数) , i∈[1,n]
    四、形式化定义:
              x≡r[1](mod b[1])
              x≡r[2](mod b[2])
                   ︰
              x≡r[n](mod b[n])
     
              设m[i]是除了b[i]的所有数的乘积m[i]=b[1]*b[2]*...*b[i-1]*b[i]...*b[n],
                      定义c[i]=m[i](m[i]¯1 mod b[i]) ;      //第一、二步就是求c[i]
                     则有a≡∑a[i]*c[i] (mod M); M=∏b[i]   //第三步
         
    五、   典型题目:猪的安家
            Andy和Mary养了很多猪。他们想要给猪安家。但是Andy没有足够的猪圈,很多猪只能够在一个猪圈安家。 举个例子,假如有16头猪,Andy建了3个猪圈,
    为了保证公平,剩下1头猪就没有地方安家了。Mary生气了,骂Andy没有脑子,并让他重新建立猪 圈。这回Andy建造了5个猪圈,但是仍然有1头猪没有地方去,
    然后Andy又建造了7个猪圈,但是还有2头没有地方去。Andy都快疯了。你对这个事情 感兴趣起来,你想通过Andy建造猪圈的过程,知道Andy家至少养了多少头
    猪。
     
    输入
     
    输入包含多组测试数据。每组数据第 一行包含一个整数n (n <= 10) – Andy建立猪圈的次数,解下来n行,每行两个整数ai, bi( bi <= ai <= 1000), 表示Andy
    建立了ai个猪圈,有bi头猪没有去处。你可以假定(ai, aj) = 1.
     
    输出
     
    输出包含一个正整数,即为Andy家至少养猪的数目。
     
    样例输入
     
    3
    3 1
    5 1
    7 2
     
    样例输出
     
    16
     
    代码如下:
     1 #include<stdio.h>  
    2 int main()
    3 {
    4 int M,Mn,result;
    5 int r[10],b[10],i,j,n;
    6 while (~scanf("%d",&n))
    7 {
    8 result=0;
    9 M=1;
    10 for(i=0;i<n;i++)
    11 {
    12 scanf("%d %d",b+i,r+i);
    13 M*=b[i];
    14 }
    15 for(i=0;i<n;i++)
    16 {
    17 Mn=M/b[i];
    18 for(j=1;(Mn*j)%b[i]!=1;j++); //求乘法逆元,也可以用上面的扩展欧几里得算法
    19 result+=Mn*r[i]*j;

    20 }
    21 printf("%d\n",result%M);
    22 }
    23 return 0;
    24 }
  • 相关阅读:
    [Windows]Windows的访问控制模型
    [C/C++]宽字符与控制台程序
    [SQL Server]自动化附加和分离数据库
    [ASP.NET]自动发送邮件功能的实现
    [Windows]Windows路径探究
    asp.net中怎么样获取前一页地址
    CheckBox全选CheckBoxList
    远程SQL插入数据
    SQL存储过程调用作业的方法
    [转]javascript 调用后台函数
  • 原文地址:https://www.cnblogs.com/Seiyagoo/p/2410369.html
Copyright © 2020-2023  润新知