• poj2891--扩展欧几里德算法


    /*
    该题使用的是扩展欧几里德算法,求模线性同余方程;
    分析题目:以题目输出结果为例 ,要求得到一个整数X可以满足 X % a = r,a,r,为数组名;
    设数组元素为两个时, 
    列出方程:X % a1 = r1;
              X % a2 = r2;
    可得出:  a1*k1 + r1 = X;
              a2*k2 + r2 = X;
    合并方程:a1*k1 + r1 = a2*k2 + r2,经变形得
              a1*k1 - a2*k2 = r2 - r1;
    由扩展欧几里德算法公式:ax + by = c;
    得到 k1, 再将 k1 反代入 a1*k1 + r1 = X 中得到 X ,
    于是X就是这两个方程的一个特解,通解就是 X'=X+k*LCM(m1,m2)
    这个式子再一变形,得 X' mod LCM(m1,m2)=X
    这个方程一出来,说明我们实现了(1)(2)两个方程的合并。
    令 M=LCM(m1,m2),R=r2-r1
    就可将合并后的方程记为 X mod M = R。 
    */
    #include<iostream>
    #define LL long long
    using namespace std;
    void gcd(LL a,LL b,LL &d,LL &x,LL &y){
        if(!b){
            d=a;x=1;y=0;
        }
        else{
            gcd(b,a%b,d,y,x);
            y-=x*(a/b);
        }
    }
    LL get(LL *a,LL *r,int n){
        LL A=a[0],R=r[0],d,x,y,sum,T;
        for(int i=1;i<n;i++){
            gcd(A,a[i],d,x,y);
            if((r[i]-R)%d!=0)
            return -1;
            x=x*(r[i]-R)/d;
            T=a[i]/d;
            x=x%T;//得到x的最小整数解 
            R=A*x+R;//将x代入回原方程 
            A=A*a[i]/d;//求最小公倍数 
            R=R%A;
        }
        return R>0?R:R+A;
    }
    int main(){
        int n;
        while(cin>>n){
            LL a[100000],r[100000];
            for(int i=0;i<n;i++){
                cin>>a[i]>>r[i];
            }
            cout<<get(a,r,n)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    [CF1166E] The LCMs Must be Large
    AtCoder Beginner Contest 161
    [CF1168B] Good Triple
    [CF1172B] Nauuo and Circle
    [CF1185E] Polycarp and Snakes
    [CF1187E] Tree Painting
    Codeforces Round #631 (Div. 2)
    [CF1200E] Compress Words
    Thinkphp绕过宝塔getshell
    如何成为一个漏洞赏金猎人
  • 原文地址:https://www.cnblogs.com/tz346125264/p/4869113.html
Copyright © 2020-2023  润新知