SCL--CRT(中国剩余定理)

2015-09-18 22:44:20

总结:复习了一下CRT,整理出这个板子。

核心方程(1):,几个同余方程模数非互素,可以计算出所有模数的所有素因子的最高幂形 p^k,然后CRT。

核心方程(2):    

  有整数解。并且在模下的解是唯一的,解为

        

   其中,而的逆元。(这部分转自ACdreamer‘s blog

1:m1,m2 ... mk 互质的情况下

inline ll mulmod(ll x,ll y,ll mod){
    ll res = 0;
    __asm__("movq %1,%%rax\n imulq %2\n idivq %3\n":"=d"(res):"m"(x),"m"(y),
            "m"(mod):"%rax");
    return res;
}

ll Ex_gcd(ll a,ll b,ll &x,ll &y){
    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }
    ll r = Ex_gcd(b,a % b,y,x);
    y -= x * (a / b);
    return r;
}

ll CRT(ll a[],ll m[],ll n){
    ll M = 1;
    for(int i = 1; i <= n; ++i) M *= m[i];
    ll res = 0;
    for(int i = 1; i <= n; ++i){
        ll x,y;
        ll Mi = M / m[i];
        Ex_gcd(Mi,m[i],x,y);
        ll tmp = mulmod(mulmod(Mi,x,M),a[i],M);
        res = (res + tmp) % M;
    }
    return (res + M) % M;
}

 

2:m1,m2 ... mk 不互质的情况下,转载自http://yzmduncan.iteye.com/blog/1323599/

 1 ll Mod;
 2 
 3 ll gcd(ll a,ll b)  {
 4     return b == 0 ? a : gcd(b,a % b);  
 5 }  
 6 
 7 ll Extend_Euclid(ll a,ll b,ll &x,ll &y){  
 8     if(b == 0){
 9         x = 1,y = 0;
10         return a;  
11     }  
12     ll d = Extend_Euclid(b,a % b,x,y);  
13     ll t = x;  
14     x = y;  
15     y = t - a / b * y;  
16     return d;  
17 }  
18 
19 //a在模n乘法下的逆元,没有则返回-1  
20 ll inv(ll a,ll n)  {
21     ll x,y;  
22     ll t = Extend_Euclid(a,n,x,y);  
23     if(t != 1) return -1;
24     return (x % n + n) % n;
25 }  
26 
27 //将两个方程合并为一个  
28 bool merge(ll a1,ll n1,ll a2,ll n2,ll &a3,ll &n3)  {
29     ll d = gcd(n1,n2);  
30     ll c = a2 - a1;  
31     if(c % d) return false;  
32     c = (c % n2 + n2) % n2;  
33     c /= d; 
34     n1 /= d;  
35     n2 /= d;  
36     c *= inv(n1,n2);  
37     c %= n2;  
38     c *= n1 * d;  
39     c += a1;  
40     n3 = n1 * n2 * d;  
41     a3 = (c % n3 + n3) % n3;  
42     return true;  
43 }  
44 
45 //求模线性方程组x=ai(mod ni),ni可以不互质  
46 ll China_Reminder2(int len,ll *a,ll *n)  {
47     ll a1 = a[1],n1 = n[1];
48     ll a2,n2;  
49     for(int i = 2; i <= len; i++){
50         ll aa,nn;  
51         a2 = a[i],n2=n[i];  
52         if(!merge(a1,n1,a2,n2,aa,nn)) return -1;  
53         a1 = aa;  
54         n1 = nn;  
55     }
56     Mod = n1;
57     return (a1 % n1 + n1) % n1;
58 }
59 
60 ll a[1000],b[1000];
61 
62 int main(){
63     .....
64     ll ans = China_Reminder2(N,a,b);
65     return 0;
66 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4820585.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值