zoukankan      html  css  js  c++  java
  • 逆元板子集

    其实就是怕忘了……这里发一下线性求逆元以及阶乘的逆元的板子。

    线性求逆元

    逆元是啥我就不说了,但是线性递推式怎么来的我还是可以证明一下的。

    求 i 的逆元,假设[1, i - 1]的逆元已知。

    设 p = k * i + b,则 b = p % i, k = ⌊p / i⌋ 。

    则k * i + b Ξ 0 (mod p),所以b Ξ - k * i。

    两边同乘inv[b]得:inv[b] * b Ξ - k * i * inv[b] (mod p)

    化简得:    - k * i * inv[b] Ξ 1 (mod p)

    两边同乘inv[i]得:inv[i] Ξ - k *inv[b] (mod p)

            inv[i] Ξ (p - k) * inv[b]

            inv[i] Ξ (p - ⌊p / i⌋) * inv[p % i]

    所以      inv[i] = (p - ⌊p / i⌋) * inv[p %i] % p

    装模作样来个代码。

    1 inv[1] = 1;
    2 for(int i = 2; i <= n; ++i) inv[i] = inv[mod % i] * (mod - mod / i) % mod;

    线性求阶乘的逆元

    其实就是根据inv[i] = inv[i + 1] * (i + 1) % p倒着递推而来。

    先用费马小定理求出inv[n]的逆元,然后倒着递推。

     1 ll quickpow(ll a, ll b)
     2 {
     3     a %= mod;
     4     ll ret = 1;
     5     for(; b; b >>= 1, a = a * a % mod) 
     6         if(b & 1) ret = ret * a % mod;
     7     return ret;
     8 }
     9 ll fac[maxn], inv[maxn];
    10 void init(int n)
    11 {
    12     fac[1] = 1;
    13     for(int i = 2; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
    14     inv[n] = quickpow(fac[n], mod - 2);
    15     for(int i = n - 1; i; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
    16 }
  • 相关阅读:
    【HDOJ】2267 How Many People Can Survive
    【HDOJ】2268 How To Use The Car
    【HDOJ】2266 How Many Equations Can You Find
    【POJ】2278 DNA Sequence
    【ZOJ】3430 Detect the Virus
    【HDOJ】2896 病毒侵袭
    求奇数的乘积
    平方和与立方和
    求数列的和
    水仙花数
  • 原文地址:https://www.cnblogs.com/mrclr/p/9833765.html
Copyright © 2011-2022 走看看