简单数论

· · 个人记录

数学太恶心了 心态爆炸

第一部分 质数和约数

一些常识

素数无限

\sum_{i = 1}^{n}\frac{1}{i} = O(logn)

欧拉筛,欧拉函数,欧拉定理

这个东西还是有很多骚操作的。

欧拉筛
void LE(int n){
    memset(flag,1,sizeof flag);
    flag[1] = 0;
    for(int i = 2 ;i <= n; i++)
    {
        if(flag[i] == 1)
        {
            prime[++tot] = i;
            phi[i] = i - 1;
        }
        for(int j = 1 ;j <= tot && i*prime[j]<=n;j++)
        {
            flag[i*prime[j]] = 0;
            if(i%prime[j] == 0)
            {
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]] = phi[i]*phi[prime[j]];
        }

    }
}
欧拉函数

如果 (a,b) = 1 , \varphi (a\cdot b) = \varphi (a) \cdot \varphi (b)
如果 ab 为质数 \varphi (a\cdot b) = \varphi (a) \cdot \varphi (b)
如果 (a,b) \neq 1, \varphi (a\cdot b) = \varphi (a) \cdot b

欧拉定理及扩展

如果 (a,m),a^{\varphi (m)} \equiv 1(\text{mod } m)
b \geq \varphi(p)a^b \equiv a^{b \text{ mod } \varphi(p) + φ(p)} (\text{mod } p)
b < \varphi(p)a^b \equiv a^{b} (\text{mod } p)

唯一分解定理

N = p_1^{c_1} + p_2^{c_2}$… $+ p_m^{c_m}

gcd / lcm

欧几里得算法 辗转相除

```cpp ll gcd(ll a,ll b){ if(b == 0)return a; return gcd(b,a%b); } ``` ### 第二部分 同余 #### 几条常用性质 $\left ( k,m \right ) = d ,ka\equiv k{a}'(\text{mod } m)\Rightarrow a\equiv {a}' (\text{mod } m/d) ax\equiv b(\text{mod } c) \Leftrightarrow ax + by = c a\equiv b(\text{mod } c)\Leftrightarrow c\mid b-a

裴蜀定理

ax + by = c;(a,b)|c

扩展欧几里得

ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b == 0){
        x = 1 ,y = 0;return a;
    }
    ll d = exgcd(b,a%b,x,y);
    ll tmp = x;
    x = y;
    y = tmp - (a/b)*y;
    return d;
}
gcd(a,b) = gcd(b,a\%b) ax + by = b{ x} + (a- \left \lfloor \frac{a}{b} \right \rfloor){y}

继续整理即可。

求逆元

1.费马小定理 a^{p} \equiv a(\text{mod } p),p 为质数, 所以 a 的逆元为 a^{p-2};
2.exgcd 求解同余方程 ax \equiv 1(\text{mod } b)\Rightarrow ax + by = 1

1~n的逆元
    inv[0] = inv[1] = 1;
    for(int i = 2 ;i <= n ;i++)
    inv[i] = (p - p/i)*inv[p%i]%p;
a[1] ~a[n]的逆元
    for(int i = 1 ;i <= n ;i++){
        a[i] = readl();
        sum[i] = (sum[i-1] * a[i])%p;
    }
    s[n] = qp(sum[n],p - 2);
    for(int i = n - 1; i >= 1 ;i--)
    s[i] = (s[i+1] * a[i+1])%p;
    sum[i] * s[i]//为逆元

CRT(中国剩余定理)

x = b_{i}(\text{mod } a_{i}) \cdots\cdots

a_{1} ,a_{2} …… a_{n} 两两互质

M = \prod_{1}^{n} a_{i}, {m}'_{i} = \frac{M}{a_{i}},t_{i}*{m}'_{i}≡1(\text{mod }a_{i}) x= \sum_{1}^{n}b_{i}*{m}'_{i}*t_{i}

m_{1} ,m_{2} …… m_{n} 两两不互质,则可将方程依次两两合并 为 x≡m_{1}×t_{0}+b_{1}\text{mod }lcm(m_{1},m_{2})) 先求解 t_{0},再带入求 x

    for(int i = 1 ; i < n ;i++){
        r2 = p[i+1],m2 = q[i+1];
        ll a = m1,b = m2,c = r2 - r1;
        ll d = exgcd(a,b,x,y);
        if(c%d){cout<<0;return 0;}
        x = ((x*c/d) + (b/d))%(b/d);
        ll mod = lcm(m2,m1);
        ll x0 = (m1*x + r1 )%mod;
        r1 = x0 ; m1 = mod;if(r1 < 0)r1 += mod;
    }

BSGS

将 $x$ 分解为$i\cdot t - p

则有a^{i\cdot t} = b\cdot a^{p}(\text{mod }m)

$ 0 < p < t$ 枚举 $p$ 计算出每一个 $a^{p}$ 的值存入hash 再枚举 $i$,算出 $a^{i\cdot t}$的值在hash中查找 ```cpp ll bsgs(ll a,ll b,ll p) { map <ll,ll> hash ;hash.clear(); ll t = sqrt(p) + 1,j; b %= p; for(int i = 0 ; i < t ;i++) { ll tmp = b * qp(a,i,p) % p; hash[tmp] = i; } a = qp(a,t,p); if(a == 0) { if(b == 0)return 1; else return -1; } for(int i = 0 ;i <= t ;i++) { ll tmp = qp(a,i,p); if(hash.find(tmp) == hash.end()) j = -1; else j = hash[tmp]; if(i*t-j >=0&&j >= 0)return i*t-j; } return -1; } ``` ### 例题 [P5431 【模板】乘法逆元2](https://www.luogu.org/problemnew/show/P5431) [P4777 【模板】扩展中国剩余定理(EXCRT)](https://www.luogu.org/problemnew/show/P4777) [P4139 上帝与集合的正确用法](https://www.luogu.org/problemnew/show/P4139) [P2485 [SDOI2011]计算器](https://www.luogu.org/problemnew/show/P2485) [P3811 【模板】乘法逆元](https://www.luogu.org/problemnew/show/P3811)