• 数论初步


    《算法竞赛入门经典》 10.1 数论初步学习总结

    这部分内容在信息安全数学基础这门课里都有涉及,不过我没听课就是了,顺便补充代码部分。

    一、欧几里得算法和唯一分解定理

    Euclid Algorithm 用来求两整数的最大公因数,一言概之: 被除数与除数的最大公约数为除数与余数的最大公约数,当除数为零时,该公约数为被除数。(0是任何数的0倍) 又称辗转相除法。

    int gcd ( int a , int b ) {
          return b==0 ? a : gcd ( b , a % b ) ;  
    }    

    又因唯一分解定理,任何数可写成多个素数的乘积。

    a = p1e1p2e2p3e3...prer;      b = p1f1p2f2p3f3...prfr
    gcd(a,b) 为 p1 到 p2 乘积, 指数为er fr 中小的; lcm(a,b) 的指数为 大的。因此两者乘积对应素数的指数固定为er+fr,即gcd(a,b) * lcm(a,b) = a * b。

    二、 Eratosthenes 筛法

    求1到n之间的所有素数, 筛法顾名思义, 在n个数中删除非素数即可。对于不超过n的每个非负整数p, 依次删除2p,3p, 4p, ...... 余下的即为所有素数。

    // vis[i] 表示i已经被删除
    memset(vis, 0, sizeof(vis)); for(int i=2, i<=n; i++) for(int j=i*2; j<=n; j+=i) vis[j] = 1;

    p可限定为素数,当p取4时,要删除的数与2重复。且不能取1。 此时在二重循环前添加判断  if(!vis[i]) 即可。

    且删除时不必从2p开始,因为当p为2时已经删除,应从p*p开始删除 ; --> int j = i * i  。

    三、 扩展欧几里得算法 

    找出一对整数(x,y) , 使得 ax + by = gcd(a,b) 。

    void gcd( int a, int b, int& d, int& x, int& y){
        if(!b){ d = a; x = 1; y = 0;}
        else { gcd(b, a%b, d, y, x); y -= x * (a/b);}; 
    }

    若方程 ax + by = c 的一组整数解为 (x0, y0), 则通解为(x0+kb',y0-ka'), a' = a / gcd(a,b), b' = b / gcd(a,b), k 取任意整数。

    若g = gcd(a,b) , ax + by = g 的一组解为(x0,y0), 则当c为g的整数倍时, ax+by=c的一组解为(x0c/g,y0c/g) , 当c不是g 的倍数时 该式无解。

  • 相关阅读:
    【模板】Sparse-Table
    UVa 11235 Frequent values
    【模板】树状数组
    UVa 1428 Ping pong
    数学技巧
    UVa 11300 Spreading the Wealth
    UVa 11729 Commando War
    UVa 11292 Dragon of Loowater
    POJ 3627 Bookshelf
    POJ 1056 IMMEDIATE DECODABILITY
  • 原文地址:https://www.cnblogs.com/faded828x/p/13901243.html
Copyright © 2020-2023  润新知