zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x33同余 扩展欧几里得解线性同余方程组

    题目链接:http://poj.org/problem?id=2891

    解线性同余方程组,由于模数不是互质的,不能用中国剩余定理,但是可以通过扩展gcd的方法求解,时间复杂度大约是O(nlogn),当只有两个方程的时候可以容易求出解x,将x的通解凝聚成新的

    模线性方程,接下来不断输入,进行n-1次迭代,即将结果保存在x = m1(mod a1)中,然后求一个最小的解输出即可。

    代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    ll n;
    
    ll exgcd(ll a,ll b,ll &x,ll &y) {
        if(b==0){
            x=1,y=0;
            return a;
        }
        ll gcd=exgcd(b,a%b,x,y);
        ll tmp=x;
        x=y;
        y=tmp-(a/b)*y;
        return gcd;
    }
    
    int main(){
        ll m1,a1,m2,a2;
        while(cin>>n){
            scanf("%lld%lld",&a1,&m1);
            bool flag=true;
            ll lcm=a1;//前n个a的最小公倍数 
            for(int i=2;i<=n;i++){//迭代,将每次的结果都保存到a1,m1中 
                scanf("%lld%lld",&a2,&m2);    
                ll k1=0,k2=0;
                ll gcd=exgcd(a1,a2,k1,k2);
                if(!flag)continue;
                if((m2-m1)%gcd)flag=false;
                k1=k1*(m2-m1)/gcd;//算出一个特解
                k1=(k1%(a2/gcd)+a2/gcd)%(a2/gcd);//求最小的正整数解 
                lcm=a1*a2/gcd;//计算新的lcm 
                m1+=k1*a1;//特解k1*a1+m1是两个方程合并之后的新的m1, 
                a1=lcm;//新的a1,进行下一轮迭代 
            }
            if(flag)printf("%lld
    ",(m1%a1+a1)%a1);//最终的结果保存在m1中,x mod a1 = m1
            else puts("-1");
        }
        return 0;
    }

    证明:

     

     

     

  • 相关阅读:
    Event notifications
    twobin博客样式
    Http协议
    ASP.NET Web API自身对CORS的支持: CORS授权检验的实施
    理解计算机系统3
    游标-Oracle游标汇总
    Oracle10g 回收站及彻底删除table : drop table xx purge
    ora-01031:insufficient privileges
    &&运算符和||运算符的优先级问题 专题
    oracle connect by 和start with
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13183409.html
Copyright © 2011-2022 走看看