中国剩余定理(CRT)

原理及例题讨论
非质数取模参考
扩展中国剩余定理,使用非互质情况

如何利用中国剩余定理求解非质数取模即注意事项,以及为什么可以这样做?

例题

举例,比如模37035
mo = 37035
假设一个很大的数A=105641,要计算Amod(mo)=B
计算B的方法为:
首先通过质数分解后 37035=95823,然后分别计算A对于9,5,823的取模结果,然后利用中国剩余定理计算最小的能够满足模9,5,823的结果与已知结果相同的最小的数。
证明:
隐含条件:A对9,5,823的取模结果与B对9,5,823的取模结果相同。
假设我们按照中国剩余定理求出的所有数的集合C中的最小值为 C 0 C_0 C0,那么C的集合是什么呢?
由于9,5,823之前两两互质,为了满足 C i C_i Ci的取模结果不变,那么必然要加一个9,5,823的最小公倍数,也就是A。
所以C的集合就是以 C 0 C_0 C0为首项,公差为A的等差数列。
显然B就在这个数列内,且B小于A,那么B必然是这个数列中的首项,也就是最小值。
注意事项:
(1)我们这样转化就是为了利用质数的逆元方法,通过计算因数对A的取模结果,从而计算出B,但是如果因数本身不是质数,那么就要小心了。
(2)如果是质数时,需要考虑也并不是一定就可以用逆元,因为逆元的前提是除法的分母与mo互质,假如分母可以整除mo的话,即使mo是质数也不能直接用,需要对其进行特殊处理。(例题解法中就对3,5,823进行了特殊处理)

板子

互质板子

这里的u[]数组为模数数组

void exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(!b){
            x = 1, y = 0;
            return;
        }
        exgcd(b, a % b, x, y);
        ll t = x;
        x = y, y = t - (a / b) * y;
    }

    ll gunc(vector<ll>&res){
        ll ans = 0;
        ll out = 1;
        for(int i = 0;i<3;i++){
            out = out*u[i];
        }
        for(int i = 0;i<3;i++){
            ll s = out/u[i];
            ll x = 0,y = 0;
            exgcd(s,u[i],x,y);
            if(x<0)
                x += u[i];
            ans += s*x*res[i];
        }
        ans = ans%out;
        return ans;
    }

非互质&互质共用板子

ll exgcd(ll a, ll b, ll &x, ll &y){
        if(b==0){
            x = 1, y = 0;
            return a;
        }
        ll d, x1, y1;
        d = exgcd(b, a%b, x1, y1);
        x = y1, y = x1 - a/b*y1;
        return d;
    }

    ll excrt(vector<ll>& m, vector<ll>& r){
        int n = m.size();
        ll m1, m2, r1, r2, p, q;
        m1 = m[0], r1 = r[0];
        for(int i = 1; i < n; ++i){
            m2 = m[i], r2 = r[i];
            ll d = exgcd(m1, m2, p, q);
            if( (r2-r1)%d !=0 ) return -1; // 不能整除,说明无解
            p = p*(r2-r1)/d;
            p = (p%(m2/d) + (m2/d))%(m2/d);
            r1 = m1*p+r1;
            m1 = m1*m2/d;
        }
        return (r1%m1+m1)%m1;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值