zoukankan      html  css  js  c++  java
  • 8.15 数论 线性同余方程组(crt 与 excrt

    crt:

    问题:

    求解形如:

    的方程组

    构造思想求解:

    构造解 X = x1 + x2 + x3 +......+xn

    其中 xi 的构造为  bi * (逆元项)*(消参项)

    消参项: 使得 除了xi的其他项xj mod ai == 0

    逆元项: 为消参项在mod ai 意义下的逆元 ,使得 bi * (逆元项)*(消参项)mod ai = bi mod ai

    则: $$Xequiv b_{i}  (mod  a_{i} ) , 1leq ileq  n $$ ,即满足要求.

    不难想到消参项的构造 :

                         $$M_{i} =  prod_{1}^{n}a / a_{i}$$

    又 ,对于通解X,任何    $ X + n*prod_{1}^{n}a  $ 都是可行解,

    所以 ,令 $ t = prod_{1}^{n}a / a_{i} $ , 则最小正整数解为 $(X; mod ;t + t ) ;mod; t$

    伪代码:

    1 → n
    0 → ans
    for i = 1 to k
        n * n[i] → n
    for i = 1 to k
        n / n[i] → m
        inv(m, n[i]) → b               // b * m mod n[i] = 1
        (ans + m * b) mod n → ans
    return (ans mod t + t ) mod t

    excrt:

    即上述方程中ai不互质的情况 ,这样的话消参项的构造就不能保证ai本身不会被消了

    但这种情况下,模数不互质的同余方程的解是有重叠的,可以用扩展欧几里得定理和线性同余方程的性质进行合并,详见:

    https://oi-wiki.org/math/crt/

     excrt = 用exgcd 求 crt

    一道例题: 

    Strange Way to Express Integers

    excrt的模板题

    将同余方程组用exgcd合并成一个方程组求解

    合并过程:

    则:

    $$x = t_{1}*b_{1} + a_{1} = t_{2}*b_{2} + a_{2} $$

    有:

    $$t_{1}*b_{1}  - t_{2}*b_{2} = a_{2}- a_{1}$$

    此方程可解,解出最小正整数解$t_{1}$ 或 $t_{2}$代入原方程组就可得合并后的方程,

    模数变成$lcm( b_{1} , b_{2})$,(因为同时能被$b_{1} , b_{2}$模得$x$);

    1.结果会很大,要用ll ,注意多组数据

    2.puts( )出的结果自带空行

    代码:

    // excrt --- 用exgcd 求 crt
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 500050;
    ll ex_gcd( ll a ,ll b ,ll &x ,ll &y ){
          if( b==0 ){
             x = 1;
             y = 0;
            return a;
          }
          ll d = ex_gcd( b ,a%b , x ,y );
          ll tmp = x;
          x = y;
          y = tmp - a/b * y;
          return d;
    }
    
    bool equ( ll a ,ll b ,ll c ,ll &x ,ll &y ,ll &g){
         g = ex_gcd( a ,b ,x ,y );
         if( c%g ) return 0;
         ll k = c/g ,t = b/g;
         x *= k;
         y *= k;
         x = (x % t + t)%t;
         return 1;
    }
    
    ll n;
    ll a[N] ,b[N];
    
    int main( ){
         while( ~scanf("%lld" ,&n) ){
                 int flag  = 0;
                 for( int i =1 ;i<=n ;i++ ){
                     scanf("%lld%lld" ,b+i ,a+i);
                 }
                 ll ans = 0 ,x ,y ,g;
    
                 for( int i = 1 ;i<n ;i++ ){
                     if( equ( b[i] ,b[i+1] ,a[i+1] - a[i] ,x ,y ,g) ){
                         a[i+1] = x*b[i] + a[i];
                         b[i+1] = b[i]/g*b[i+1];
                     }
                     else {
                         puts( "-1" );
                         flag = 1;
                         break;
                     }
                 }
                 if( flag )continue;
                 printf( "%lld
    " ,a[n]%b[n] );
            }
         return 0;
    }
  • 相关阅读:
    QOMO Linux 4.0 正式版发布
    LinkChecker 8.1 发布,网页链接检查
    pgBadger 2.1 发布,PG 日志分析
    Aletheia 0.1.1 发布,HTTP 调试工具
    Teiid 8.2 Beta1 发布,数据虚拟化系统
    zLogFabric 2.2 发布,集中式日志存储系统
    开源电子工作套件 Arduino Start Kit 登场
    Piwik 1.9 发布,网站访问统计系统
    Ruby 1.9.3p286 发布,安全修复版本
    toBraille 1.1.2 发布,Java 盲文库
  • 原文地址:https://www.cnblogs.com/-ifrush/p/11356791.html
Copyright © 2011-2022 走看看