• EXCRT


    是个好东西,可以处理在模数不互质的同余方程组

    核心就是用扩欧来合并方程

    如果我们有两个形如(xequiv b_1(mod a_1)) (xequiv b_2(mod a_2))的方程我们要将他们合并

    就是利用各种操作化柿子

    [x=a_1k_1+b_1=a_2k_2+b_2 ]

    随便移一下

    [a_1k_1=b_2-b_1+a_2k_2 ]

    根据贝祖定理((a1,a2)|(b_2-b_1))时候才有解

    如果有解得话,我们只需要在两边除以((a1,a2))

    那么就有

    [frac{a_1k_1}{(a_1,a_2)}=frac{b_2-b_1}{(a_1,a_2)}+frac{a_2k_2}{(a_1,a_2)} ]

    我们也可以写成同余的形式

    [frac{a_1k_1}{(a_1,a_2)}equiv frac{b_2-b_1}{(a_1,a_2)}(mod frac{a_2}{(a_1,a_2)}) ]

    让左边只留下(k_1),就是把逆元乘过去

    [k_1equiv inv(frac{a_1}{(a_1,a_2)},frac{a_2}{(a_1,a_2)})*frac{b_2-b_1}{(a_1,a_2)}(mod frac{a_2}{(a_1,a_2)}) ]

    再将同余式写成等式

    [k_1=inv(frac{a_1}{(a_1,a_2)},frac{a_2}{(a_1,a_2)})*frac{b_2-b_1}{(a_1,a_2)}+frac{a_2}{(a_1,a_2)}*y ]

    再回带到(x)里去

    [x=inv(frac{a_1}{(a_1,a_2)},frac{a_2}{(a_1,a_2)})*frac{b_2-b_1}{(a_1,a_2)}*a_1+frac{a_2a_1}{(a_1,a_2)}*y+b_1 ]

    现在我们再写成同余式

    [xequiv inv(frac{a_1}{(a_1,a_2)},frac{a_2}{(a_1,a_2)})*frac{b_2-b_1}{(a_1,a_2)}*a_1\%frac{a_2}{(a_1,a_2)}+b_1(mod frac{a_1a_2}{(a_1,a_2)}) ]

    现在两个方程不就被合并好了吗

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 100005
    #define LL long long
    LL x,y;
    LL gcd(LL a,LL b)
    {
        if(!b) return a;
        return gcd(b,a%b);
    }
    LL exgcd(LL a,LL b,LL &x,LL &y)
    {
        if(!b) return x=1,y=0,a;
        LL r=exgcd(b,a%b,y,x);
        y-=a/b*x;
        return r;
    }
    int n;
    LL a[maxn],b[maxn];
    inline LL read()
    {
        char c=getchar();
        LL x=0;
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9')
            x=(x<<3)+(x<<1)+c-48,c=getchar();
        return x;
    }
    inline LL inv(LL a,LL b)
    {
        LL r=exgcd(a,b,x,y);
        LL t=b/r;
        return (x%t+t)%t;
    }
    inline LL mul(LL a,LL b)
    {
        LL S=0;
        while(b)
        {
            if(b&1ll) S=S+a;
            b>>=1ll;
            a=a+a;
        }
        return S;
    }
    void write(LL x)
    {
    	if(x>9) write(x/10);
    	putchar(x%10+48);
    }
    int main()
    {
        n=read();
        for(re int i=1;i<=n;i++)
            a[i]=read(),b[i]=read();
        LL r=gcd(a[1],a[2]);
        LL A=mul(a[1],a[2]/r);
        LL B=(inv(a[1]/r,a[2]/r)*(b[2]-b[1])/r%(a[2]/r)+a[2]/r)%(a[2]/r)*a[1]+b[1];
        for(re int i=3;i<=n;i++)
        {
            LL r=gcd(A,a[i]);
            B=(inv(A/r,a[i]/r)*(b[i]-B)/r%(a[i]/r)+a[i]/r)%(a[i]/r)*A+B;
            A=mul(A,a[i]/r);
        }
        write(B);
        return 0;
    }
    
  • 相关阅读:
    js自定义事件
    js回调函数
    git和github使用
    23种设计模式(10):命令模式
    HBase查询引擎——Phoenix的使用
    八、shell的管道
    七、Linux的shell的重定向
    五、Linux的常用命令 和 使用方式 1
    十二、TestNG分组测试2
    十一、TestNG依赖测试
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207873.html
Copyright © 2020-2023  润新知