• 扩展CRT学习笔记


    中国剩余定理是用来解同余方程组的

    ${x} equiv {r_1} (mod ;p_1)$

    ${x} equiv {r_2} (mod ;p_2)$

    $...$

    ${x} equiv {r_n} (mod ;p_n)$

    但是构造法只能求解$p$都互质的情况,那当$p$不互质怎么办办勒把出题人吊起来打一顿就好了

    然而NOI时好像不能跑出考场阿掉出题人啊~~~

    那我们可以考虑两个同余方程

    ${x} equiv {r_1} (mod ;p_1)$

    ${x} equiv {r_2} (mod ;p_2)$

    我们试图把它们合并成一个,如果成功了,我们就可以把n个方程合并成一个,然后就可以出解啦

    怎么合并勒?

    发现$x=r_1+k_1*p_1=r_2+k_2*p_2$

    那么${k_1*p_1}equiv{r_2-r_1}(mod;p_2)$

    那么把等式全除以$gcd(p_1,p_2)$,当$r_2-r_1$不能被整除时,就无解了

    否则我们把$p_1$和$p_2$都除以$gcd(p_1,p_2)$后就互质了,就可以求逆元啦,然后就可以求出$k_1$啦

    那么新的方程就是${x} equiv {r_1+k_1*p_1} (mod ;frac{(p_1)(p_2)}{(gcd(p_1,p_2)})$

    我的模板(由于种种原因,我加了龟速快速乘防止爆long long)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,i,j,a[500000],b[500000];
    int gcd(int a,int b)
    {
        return b?gcd(b,a%b):a;
    }
    int exgcd(int a,int b,int &x,int &y)
    {
        int t=a;
        if(!b)x=1,y=0;else t=exgcd(b,a%b,y,x),y-=(a/b)*x;
        return t;
    }
    int mul(int a,int b,int mod)
    {
        a%=mod,b%=mod;
        a=(a+mod)%mod,b=(b+mod)%mod;
        int ans=0;
        while(b)
        {
            if(b%2)ans=(ans+a)%mod;
            a=a*2%mod;b=b/2;
        }
        return ans;
    }
    int CRT(int *re,int *mod,int n)
    {
        int r=0,m=1;
        for(int i=0;i<n;i++)
        {
            int g=gcd(m,mod[i]),x,y;
            if((re[i]-r)%g)return -1;
            int inv;exgcd(m/g,mod[i]/g,x,y);inv=x;
            int M=m/gcd(m,mod[i])*mod[i];
            int k1=mul((re[i]-r)/g,inv,M);
            r+=mul(k1,m,M);
            m=M;r=(r+m)%m;
        }
        return r;
    }
    main()
    {
        scanf("%lld",&n);
        for(i=1;i<=n;i++)scanf("%lld%lld",&a[i],&b[i]);
        printf("%lld",CRT(b+1,a+1,n));
        return 0;
    }
  • 相关阅读:

    list集合
    接口
    抽取对象的基本方法
    访问修饰符
    构造方法
    如何弹出一个对话框
    nginx反代配置
    TreeMap排序
    BeanPropertyRowMapper
  • 原文地址:https://www.cnblogs.com/Orange-User/p/9366477.html
Copyright © 2020-2023  润新知