首页 > 其他分享 >浅析数论

浅析数论

时间:2023-03-05 13:14:16浏览次数:45  
标签:gcd 数论 sum varphi int pmod 浅析 equiv

浅析数论

目录

更好的阅读体验戳此进入

还没写完,春测之后有机会继续写。

裴蜀定理

$ ax + by = \gcd(a, b) \iff a, b \in \mathbb{Z}^* $。特别地对于 $ a, b $ 不全为 $ 0 $ 的情况也成立。

证明略。

LG-P4549 【模板】裴蜀定理

int N;
int ans;

int main(){
    N = read();
    ans = abs(read()), --N;
    while(N--)ans = __gcd(ans, abs(read()));
    printf("%d\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

gcd

对于一般的 $ \gcd $ 这里不过多赘述,值得一提的只有:

更相减损术,即:$ \gcd(a, b) = \gcd(b, a - b) $。

更进一步地,有 $ \gcd(a, b) = \gcd(b, a \bmod{b}) $。

exgcd(线性同余方程)

对于整数 $ a, b $,要求 $ ax + by = \gcd(a, b) $。

显然存在 $ bx' + (a \bmod{b})y' = \gcd(b, a \bmod{b}) $。

又 $ \gcd(a, b) = \gcd(b, a \bmod{b}) $。

整理并展开 $ a \bmod b $ 得到 $ ax + by = bx' + (a - \lfloor \dfrac{a}{b} \rfloor \times b)y' $。

则显然有 $ x = y', y = x' - \lfloor \dfrac{a}{b} \rfloor \times y $。

问题规模缩减,不断递归,直到最终 $ \gcd = 0 $,或者说 $ b = 0 $ 则回溯 $ x = 1, y = 0 $ 即可。

考虑更一般的形式,即 $ ax + by = c $,其中 $ \gcd(a, b) \mid c $。

令 $ d = \dfrac{c}{\gcd(a, b)} $,显然整除,则 $ x \leftarrow x \times d, y \leftarrow y \times d $ 即可。

此算法得到的为任意解,考虑如何得到 $ x $ 的最小非负解。

发现方程通解为 $ x + k\dfrac{b}{\gcd(a, b)}, y - k\dfrac{a}{\gcd(a, b)} $,以 $ \dfrac{b}{\gcd(a, b)} $ 为模数对 $ x $ 取模转正后求出对应的 $ y $ 即可找到 $ x $ 的最小非负解。

同时这里我们考虑线性同余方程的表示,即给定 $ a, b $,求解 $ ax \equiv c \pmod{b} $,其中 $ \gcd(a, b) \mid c $,显然我们可以将该式转化为 $ ax + by = c $ 中 $ x $ 的解的形式。

费马小定理

若 $ p $ 为质数且 $ \gcd(a, p) = 1 $,那么 $ a^{p - 1} \equiv 1 \pmod{p} $。

同时存在另一种表示形式,对于任意整数 $ a $,有 $ a^p \equiv a \pmod{p} $。

证明待补。

欧拉函数

定义欧拉函数 $ \varphi(n) $ 表示小于等于 $ n $ 的数中与 $ n $ 互质的数的个数。显然有 $ \varphi(1) = 1 $,以及对于质数 $ p $ 有 $ \varphi(p) = p - 1 $。

欧拉函数为不完全积性函数,即对于 $ a \perp b $,有 $ \varphi(a \times b) = \varphi(a) \times \varphi(b) $。

特别地,对于 $ n $ 为奇数,有 $ \varphi(2n) = \varphi(n) $。

存在 $ n = \sum_{d \mid n} \varphi(d) $,莫反易证。

特别地,对于 $ n = p^k $,有 $ \varphi(n) = p^k - p^{k - 1} $,易证。

存在 $ \varphi(n) = n \times \prod \dfrac{p_i - 1}{p_i} $。

线性筛欧拉函数

欧拉函数为不完全积性函数,即对于 $ a \perp b $,有 $ \varphi(a \times b) = \varphi(a) \times \varphi(b) $。

考虑利用此性质,在线性筛的过程中,对于当前枚举的数 $ i $ 以及枚举的质数 $ p $,若满足 $ i \not\equiv 0 \pmod{p} $ 那么一定满足 $ i \perp p $,则有 $ \varphi(i \times p) = \varphi(i) \times \varphi(p) \(。反之我们考虑欧拉函数的质因数分解求法进行推导,即:\) \varphi(i \times p) = i \times p \times \prod \dfrac{p_i - 1}{p_i} $,且我们知道此种情况下因 $ i $ 是 $ p $ 的倍数,那么 $ i $ 中一定存在质因数 $ p $,也就是说 $ i $ 的质因子种类数与 $ i \times p $ 的是相同的,于是可以转化为 $ \varphi(i \times p) = p \times \varphi(i) $。

例题 #1 LG-P2158 [SDOI2008] 仪仗队

题面不太好描述,可以去看原题面,也可以直接看转化,还是比较好理解的。

不难发现答案转化为求所有横纵坐标在 $ [1, n - 1] $ 且互质的点的个数加 $ 2 $,可感性转化为 $ \sum_{i = 1}^{n - 1} \varphi(i) \times 2 - 1 + 2 $,即对称讨论后减去主对角线上重复计算的。我们令 $ n \leftarrow n - 1 $,尝试通过交换求和严谨推导:

\[\begin{aligned} &\sum_{i = 1}^n \sum_{j = 1}^n [\gcd(i, j) = 1] \\ =&\sum_{i = 1}^n \sum_{j = 1}^i [\gcd(i, j) = 1] + \sum_{i = 1}^n \sum_{j = i}^n [\gcd(i, j) = 1] - \sum_{i = 1}^n[\gcd(i, i) = 1] \\ =&\sum_{i = 1}^n \sum_{j = 1}^i [\gcd(i, j) = 1] + \sum_{j = 1}^n \sum_{j = 1}^i [\gcd(i, j) = 1] - \sum_{i = 1}^n[\gcd(i, i) = 1] \\ =&\sum_{i = 1}^{n} \varphi(i) \times 2 - 1 \end{aligned} \]

线性筛欧拉函数即可。

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define LIM (41000)

template < typename T = int >
inline T read(void);

int N;
int phi[LIM + 100];
int ans(0);
basic_string < int > Prime;
bitset < LIM + 100 > notPrime;

int main(){phi[1] = 1;
    for(int i = 2; i <= LIM; ++i){
        if(!notPrime[i])Prime += i, phi[i] = i - 1;
        for(auto p : Prime){
            if(i * p > LIM)break;
            phi[i * p] = i % p ? phi[i] * phi[p] : p * phi[i];
            notPrime[i * p] = true;
            if(i % p == 0)break;
        }
    }N = read();
    if(N == 1)printf("0\n"), exit(0);
    for(int i = 1; i <= N - 1; ++i)ans += phi[i] * 2;
    printf("%d\n", ans + 1);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

例题 #2 LG-P2568 GCD

给定 $ n $,求满足 $ \gcd(x, y) $ 为质数的有序数对 $ (x, y) $ 有多少种。

我们令 $ m $ 为值域在 $ [1, n] $ 的质数个数,朴素推导:

\[\begin{aligned} &\sum_{i = 1}^n \sum_{j = 1}^n [\gcd(i, j) \in P] \\ =& \sum_{i = 1}^n \sum_{j = 1}^n \sum_{p} [\gcd(i, j) = p] \\ =& \sum_{p}\sum_{i = 1}^n \sum_{j = 1}^n [\gcd(\dfrac{i}{p}, \dfrac{j}{p}) = 1] \\ =& \sum_{p}\sum_{i = 1}^{\lfloor \frac{n}{p} \rfloor} \sum_{j = 1}^{\lfloor \frac{n}{p} \rfloor} [\gcd(i, j) = 1] \\ \end{aligned} \]

然后问题就转化为了 LG-P2158 [SDOI2008] 仪仗队,预处理一下即可。

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW void* Edge::operator new(size_t){static Edge* P = ed; return P++;}
#define ROPNEW_NODE void* Node::operator new(size_t){static Node* P = nd; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define LIM (11000000)

template < typename T = int >
inline T read(void);

int N;
int phi[LIM + 100];
ll ans(0);
ll sum[LIM + 100];
basic_string < int > Prime;
bitset < LIM + 100 > notPrime;

int main(){phi[1] = 1, notPrime[1] = true;
    for(int i = 2; i <= LIM; ++i){
        if(!notPrime[i])Prime += i, phi[i] = i - 1;
        for(auto p : Prime){
            if((ll)i * p > LIM)break;
            phi[i * p] = i % p ? phi[i] * phi[p] : p * phi[i];
            notPrime[i * p] = true;
            if(i % p == 0)break;
        }
    }N = read();
    for(int i = 1; i <= N; ++i)sum[i] = sum[i - 1] + phi[i] * 2;
    for(auto p : Prime){
        if(p > N)break;
        ans += sum[N / p] - 1;
    }
    printf("%lld\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

欧拉定理

若 $ \gcd(a, p) = 1 $,则有 $ a^{\varphi(m)} \equiv 1 \pmod{m} $。

证明待补。

扩展欧拉定理

即:

\[a^b = \left\{ \begin{array}{ll} a^{b \bmod{\varphi(p)}} & \gcd(a, p) = 1 \\ a^b & \gcd(a, p) \neq 1 \land b \lt \varphi(p) \\ a^{b \bmod \varphi(m) + \varphi(m)} & \gcd(a, p) \neq 1 \land b \ge \varphi(p) \end{array} \right. \]

一般用于在快速幂时幂次过高的情况。

证明待补。

乘法逆元

对于线性同余方程 $ ax \equiv 1 \pmod{p} $,则称 $ x $ 为 $ a $ 在模 $ p $ 意义下的乘法逆元,记作 $ a^{-1} $。一般用于解决除法中不适用于分子分母同时取模的缺陷。

首先若 $ p $ 为质数,且 $ a, p $ 互质,那么考虑使用费马小定理,$ a^{p - 1} \equiv 1 \pmod{p} \iff a \times a^{p - 2} \equiv 1 \pmod{p} $。那么 $ a^{-1} = a^{p - 2} $,也就是说 $ a $ 在模 $ p $ 意义下的乘法逆元为 $ a^{p - 2} $。

考虑更一般的情况,若不满足 $ p $ 为质数,但满足 $ a \perp p $,则可以考虑使用 exgcd,即求出 $ ax + py = 1 $ 的 $ x $ 的最小非负解,则有 $ a^{-1} = x $。

而对于更加一般的情况,可以发现其不存在乘法逆元。

CRT(中国剩余定理)

大致就是要解决如下同余式:

\[\left\{ \begin{array}{c} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \vdots \\ x \equiv a_n \pmod{m_n} \end{array} \right. \]

其中满足 $ m_1, m_2, \cdots, m_n $ 两两互质。

大致的思路就是考虑对问题进行拆分,显然若拆分为 $ x_1 \equiv 1 \pmod{m_1}, x_1 \equiv 0 \pmod{m_r}(r \neq 1) $,对于 $ x_2, x_3, \cdots, x_n $ 同理定义,此时 $ x = \sum_{i = 1}^n a_i x_i $ 即为答案。

我们单独考虑一个 $ x_1 $,显然其应为 $ m_2, m_3, \cdots $ 的倍数,令 $ p = \prod_{i = 2}^n m_i $,则应有 $ x_1 = kp $,即 $ kp \equiv 1 \pmod{m_1} $,则 $ k $ 为 $ p $ 在模 $ m_1 $ 意义下的逆元。

更具体地说,假设 $ M = \prod m_i $,那么应有 $ x_i = \dfrac{M}{m_i}(\dfrac{M}{m_i})^{-1} $,注意这里的逆元是模 $ m_i $ 意义下的,但此乘积不能对 $ m_i $ 取模(对于这里的不能取模再详细解释一下,即我们这里是想要求出 $ k $ 与 $ p $ 并乘起来,而不是想要求 $ kp \bmod{m_i} $,我们只是知道 $ k $ 与 $ p $ 在模 $ m_i $ 意义下互为逆元。换句话说如果直接乘起来就会变成 $ 1 $ 了)。

最终 $ \sum_{i = 1}^n a_ix_i \bmod{M} $ 即为模 $ M $ 意义下的唯一解。

同时注意这里只满足 $ m_i $ 之间互质,但不满足 $ m_i $ 为质数,则只能用 exgcd 求解乘法逆元,不能使用费马小定理。

LG-P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪

int N;
int A[20], B[20];
ll mul(1);
ll ans(0);

void exgcd(ll a, ll b, ll &x, ll &y){
    if(!b)return x = 1, y = 0, void();
    exgcd(b, a % b, x, y);
    ll tmp(x);
    x = y, y = tmp - a / b * y;
}
ll CalInv(ll a, ll b){
    ll x, y; exgcd(a, b, x, y);
    ll mod = b / __gcd(a, b);
    return (x % mod + mod) % mod;
}

int main(){
    N = read();
    for(int i = 1; i <= N; ++i)A[i] = read(), B[i] = read();
    for(int i = 1; i <= N; ++i)mul *= A[i];
    for(int i = 1; i <= N; ++i)(ans += B[i] * (mul / A[i]) * CalInv(mul / A[i], A[i]) % mul) %= mul;
    printf("%lld\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

Garner算法

首先同样存在如下同余式:

\[\left\{ \begin{array}{c} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \vdots \\ x \equiv a_n \pmod{m_n} \end{array} \right. \]

我们的目的是将 $ x $ 拆分为若干质数,则有结论,若 $ x \lt \prod m_i $,我们可以将 $ x $ 拆分(称作混合基数表示)为:

\[x = x_1 + m_1x_2 + m_1m_2x_3 + \cdots + m_1m_2\cdots m_{k - 1}x_k \]

可以进行如下拆分的正确性也较为显然,首先考虑 CRT,我们需要表示出所有满足 $ x_1 \equiv a_1, x_2 \equiv a_2, \cdots $,于此我们考虑经典的群论套路,任意的 $ x_1 \bmod{m_1} $ 一定可以表示出 $ a_1 $,而 $ m_1x_2 $,因为 $ m_1 \perp m_2 $,则 $ km_1 \bmod{m_2} $ 的环有且仅有一个,所以 $ m_1x_2 $ 可以表示出模 $ m_2 $ 意义下的所有数,包括 $ a_2 $,同理 $ m_1m_2 \perp m_3 $,以此类推。

则也类似这个思路,不难想到 $ x_1 \equiv a_1 \pmod{m_1}, m_1x_2 \equiv a_2 \pmod{m_2}, \cdots \ $。

我们令 $ inv(i, j) $ 表示 $ i $ 在 $ j $ 意义下的逆元,则:$ x_2 = a_2 \times inv(m_1, m_2) \bmod{m_2}, x_3 = a_2 \times inv(m_1, m_3) \times inv(m_2, m_3) \bmod{m_3}, \cdots $。

于是现在我们就成功地用大量小质数表示出一个大整数。

exCRT(扩展中国剩余定理)

还是一样的同余式:

\[\left\{ \begin{array}{c} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \vdots \\ x \equiv a_n \pmod{m_n} \end{array} \right. \]

但是不满足 $ m_1, m_2, \cdots, m_n $ 之间两两互质。

虽然是 exCRT 但是除了问题相似之外与 CRT 似乎没什么关系。

首先考虑存在两个同余方程:

\[\left\{ \begin{array}{c} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \end{array} \right. \]

考虑对于线性同余方程的常规转化:

\[\left\{ \begin{array}{c} x = a_1 + b_1m_1 \\ x = a_2 + b_2m_2 \end{array} \right. \]

有:$ a_1 + b_1m_1 = a_2 + b_2m_2 $,整理得到 $ b_1m_1 + (-b_2)m_2 = a_2 - a_1 $。

可以用 exgcd 求得 $ b_1m_1 + (-b_2)m_2 = \gcd(m_1, m_2) $ 的解 $ b_1', b_2' $,同时有 $ d = \dfrac{a_2 - a_1}{\gcd(m_1, m_2)} $,于是有:

\[(db_1')m_1 + (db_2')m_2 = a_2 - a_1 \]

所以现在我们以 $ x = a_1 + b_1m_1 $ 为例,我们显然要最小化 $ b_1 $,于是我们取方程中 $ b_1' $ 的最小非负解,或者说实际上取得应为 $ db_1’ $ 的最小非负解,即 $ b_1 = db_1' $。

Tips:读到这里不难发现,若不满足 $ \gcd(m_1, m_2) \mid a_2 - a_1 $,则方程无解。

于是此时我们可以根据 $ b $ 得出一个满足上述两个同余方程的特解 $ x' $,且可以证明对于上述同余方程的所有解 $ x $,有 $ x = x' + k \operatorname{lcm}(m_1, m_2) $,即:

\[x \equiv x' \pmod{\operatorname{lcm}(m_1, m_2) } \]

此时两个方程被合成为了同一个,直到最终仅剩一个方程时其解即为答案。

LG-P4777 【模板】扩展中国剩余定理(EXCRT)

void exgcd(__int128_t a, __int128_t b, __int128_t &x, __int128_t &y){
    if(!b)return x = 1, y = 0, void();
    exgcd(b, a % b, x, y);
    __int128_t tmp(x);
    x = y;
    y = tmp - a / b * y;
}
void Query(__int128_t a, __int128_t b, __int128_t &x, __int128_t &y, __int128_t c){
    exgcd(a, b, x, y);
    __int128_t d = c / __gcd(a, b);
    x *= d, y *= d;
    __int128_t val = b / __gcd(a, b);
    x = (x % val + val) % val;
    y = (c - a * x) - b;
}

int N;
__int128_t rem1(-1), mod1(-1);

int main(){
    N = read();
    while(N--){
        __int128_t mod2 = read < ll >(), rem2 = read < ll >();
        if(!~rem1 || !~mod1){rem1 = rem2, mod1 = mod2; continue;}
        __int128_t b1, b2;
        Query(mod1, -mod2, b1, b2, rem2 - rem1);
        rem1 = rem1 + b1 * mod1;
        mod1 = mod1 * mod2 / __gcd(mod1, mod2);
        rem1 = (rem1 % mod1 + mod1) % mod1;
    }printf("%lld\n", rem1);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

UPD

update-2023__ 初稿

标签:gcd,数论,sum,varphi,int,pmod,浅析,equiv
From: https://www.cnblogs.com/tsawke/p/17180266.html

相关文章

  • 浅析生成函数
    浅析生成函数目录浅析生成函数更好的阅读体验戳此进入定义OGF(普通生成函数)EGF(指数生成函数)CGF(组合生成函数)PGF(概率生成函数)UPD更好的阅读体验戳此进入定义生成函数(Gene......
  • 浅析群论
    GroupTheory-浅析群论目录GroupTheory-浅析群论更好的阅读体验戳此进入群阶子群陪集定义与性质常见表述拉格朗日定理置换定义运算置换群定义群作用群对自身的作用群......
  • 数论学习笔记2:数论函数
    积性函数定义积性函数是满足\(\forallu\perpv,f(uv)=f(u)f(v)\)的数论函数,\(f(1)\)总是等于\(1\)。求值由定义可知,积性函数在全体正整数处的取值由其在\(p^k\)......
  • 【题解】P6271 [湖北省队互测2014]一个人的数论
    很久之前存的古代经典题,思路是cyj的。感谢那时候先辈们的分享精神,这就是十年前的OI圈子吗。思路莫比乌斯反演。首先注意到一个自然数幂次和,令\(F(n)=\sum\limit......
  • 浅析sleep()方法与wait()方法
    为什么wait()方法不定义在Thread中?  wait()是让获得对象锁的线程实现等待,会自动释放当前线程占有的对象锁。每个对象(Object)都拥有对象锁,既然要释放当前线程占有的......
  • 浅析厂房仓库电气火灾的成因及对策
    陈盼安科瑞电气股份有限公司上海嘉定201801摘要: 文章分析了厂房仓库电气火灾的成因及火灾特点,并有针对性地提出了预防火灾的对策。 关键词: 厂房仓库;电气火灾;成因;预......
  • NOI 2023 一轮复习Ⅰ:数论
    NOI2023一轮复习Ⅰ:数论阅读须知:本系列博客主要为个人复习所用,可供各位参考。整理的知识点不会涉及较为偏僻的知识点,以NOI考察过的知识点为主。按照目前的想法,想分......
  • 浅析大促备战过程中出现的fullGc,我们能做什么?
    作者:京东科技白洋##**前言:**```背景:为应对618、双11大促,消费金融侧会根据零售侧大促节奏进行整体系统备战。对核心流量入口承载的系统进行加固优化,排除系统风险,保证大......
  • Difficult math for ty—— 数论
    欧几里得算法根据\(\gcd(a,b)=\gcd(b,a\bmodb)\)递归。时间复杂度:\(O(\logn)\)。证明:\(a<b\),\(\gcd(a,b)=\gcd(b,a)\),变为情况2.\(a\geqb\),\(\gcd(a,b)=\gcd(......
  • 浅析nginx -s reload与service nginx restart区别及linux下nginx加载配置文件异常提示
    1、语法:nginx-ssignal。signal的值如下:stop:fastshutdown,快速的停止nginxquit:gracefulshutdown,不再接受新的请求,等正在处理的请求出完成后在进行停止(优雅的......