zoukankan      html  css  js  c++  java
  • 扩展中国剩余定理(EXCRT)快速入门

    问题

    传送门

    看到这个问题感觉很难???
    不用怕,往下看就好啦
    假如你不会CRT也没关系

    EXCRT大致思路

    先考虑将方程组两两联立解开,如先解第一个与第二个,再用第一个与第二个的通解来解第三个...(以此类推)
    那么怎么解第一个与第二个同余方程呢?

    [egin{cases} x equiv a_1 pmod{b_1}\ x equiv a_2 pmod{b_2}\ . . . end{cases} ]

    则存在整数(注意不是非负),使得

    [egin{cases} x = a_1 +k_1 * b_1\ x = a_2 +k_2 * b_2\ end{cases} ]

    所以有
    $ a_1 +k_1*b_1$ (=) $a_2 +k_2 * b_2 $
    移项可得
    $ k_1*b_1 $ (+) $k_2*b_2=a_2-a_1 $

    (注意这里可以是 $ k_1*b_1$ (+) $k_2*b_2 $ 因为 $ k_2 $ 可为负数)

    不妨令(a_2-a_1)(c)
    然后发现这里长得很像我们的 扩展欧几里得 !!!
    而根据裴蜀定理得,当且仅当 $gcd( k_1 , k_2 ) | c $ 时 该方程有整数解
    所以我们可用exgcd求出 $ k_1*b_1+k_2*b_2=gcd(k_1,k_2) $
    再等式两边同时乘以 $ c/gcd(k_1,k_2) $ 即可

    这样就可以解出 此时的式子了
    所以新的 A 为(a_1+b_1*k_1) ,新的B则为(lcm(b_1,b_2))
    然后再用新的A,B与(a_3,b_3)去计算就好
    最后的答案就是最后算出来的A

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define re register
    #define int __int128
    #define in inline 
    #define get getchar()
    in int read()
    {
        int t=0; char ch=get;
        while(ch<'0' || ch>'9') ch=get;
        while( ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
        return t;
    }
    const int _=2e5+5;
    int a[_],b[_],n;
    void out(int x) {
        if (!x) return;
        out(x / 10);
        putchar(x % 10 + '0');
    }
    in int exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)
        {
            x=1,y=0;
            return a;
        }
        int g=exgcd(b,a%b,y,x);
        y -= a / b * x;
        return g;
    }
    in int mul(int a,int b,int mod)
    {
        int res=0;
        while(b)
        {
            if(b&1)res=(res+a)%mod;
            a=(a+a)%mod,b>>=1;
         }
        return res;
    }
    in int excrt()
    {
        int a1=a[1],b1=b[1];
        for(re int i=2;i<=n;i++)
        {
            int a2=a[i],b2=b[i],x,y,c;
            c=((a2-a1)%b2+b2)%b2;
            int gcd=exgcd(b1,b2,x,y);
            if(c%gcd) return -1;
            x=mul(x,c/gcd,b2);
            a1=a1+x*b1;
            b1=b1*b2/gcd;
            a1=(a1%b1+b1)%b1;
        }
        return a1;
    }
    signed main()
    {
        n=read();
        for(re int i=1;i<=n;i++)
            b[i]=read(),a[i]=read();
        out(excrt());
        return 0;
    }
    
    
  • 相关阅读:
    struts tomcat 中文乱码解决
    struts 2 自定义模板
    xsd 生成 xsd 文件为类文件
    struts2 从 action 到 jsp 页面
    根据查询生成简单得临时表
    DBGridEh 提示 Incompatible types
    ubuntu 收集的命令
    sp_executesql 使用
    arcims [ERR0134] Requested Service is not available 错误
    mysql 备份还原数据
  • 原文地址:https://www.cnblogs.com/yzhx/p/11579069.html
Copyright © 2011-2022 走看看