数学知识学习笔记


数学知识学习笔记

一、质数

略。

二、欧拉函数

\(1\)\(n\) 中与 \(n\) 互质的数的个数称为欧拉函数,记做 \(\varphi(n)\)

若在算术基本定理中,\(n = p_1^{c_1}p_2^{c_2}p_3^{c_3} \dots p_m^{c_m}\),则:

\[\varphi(n) = n \times \frac{p_1 - 1}{p_1} \times \frac{p_2 - 1}{p_2} \dots \frac{p_m - 1}{p_m} = n \times \prod_{\text{质数}p \mid n} (1-\frac{1}{p}) \]

根据欧拉函数的计算柿,我们可以在分解质因数时「顺便」求出 \(\varphi(n)\)。代码:

int phi(int n) {
    int ans = n;
    for (int i = 2; i * i <= n; i++)
        if (n % i == 0) {
            ans = ans / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    if (n > 1) ans = ans / n * (n - 1);
    return ans;
}

欧拉函数的性质:

  1. 对于任意大于 \(1\)\(n\)\(1\)\(n\) 中与 \(n\) 互质的数的和为 \(n \times \varphi(n) \over 2\)
  2. \(a,b\) 互质,则 \(\varphi(ab) = \varphi(a)\varphi(b)\)
  3. \(p\) 为质数,若 \(p \mid n\)\(p^2 \mid n\),则 \(\varphi(n) = \varphi({n \over p}) \times p\)
  4. \(p\) 为质数,若 \(p \mid n\)\(p^2 \nmid n\),则 \(\varphi(n) = \varphi({n \over p}) \times (p-1)\)
  5. \(\sum_{d \mid n} \varphi(d) = n\)

如果当 \(a,b\) 互质时,有 \(f(ab) = f(a)f(b)\),那么称函数 \(f\)积性函数。显然,欧拉函数就是积性函数。

积性函数的性质:

\(f\) 是积性函数,且在算术基本定理中 \(n = \prod_{i=1}^m p_i^{c_i}\),则 \(f(n) = \prod_{i=1}^m f(p_i^{c_i})\)

例题 2.2 [SDOI2008] 仪仗队

原题目链接:Link

观察一下,我们可以发现,除了 \((0,1),(1,0),(1,1)\) 三个点外,一个点 \((x,y)\) 可以被看到,则 \(\gcd(x,y) = 1(1 \leq x,y \leq n, x \neq y)\)

所以,我们只需要统计每个 \(2 \leq y \leq n\),有多少个 \(x\) 满足 \(\gcd(x,y)=1(1 \leq x \leq y)\),数量显然就为 \(\varphi(y)\)。因为这些点关于对角线对称,最后的答案就为 \(3 + \sum_{i=2}^{n-1} \varphi(i)\)。特殊地,若 \(n = 1\),则答案为 \(0\)。代码如下:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 4e4 + 5;

int phi[MAXN], n, ans;
int euler(int n) {
   for (int i = 1; i <= n; i++) phi[i] = i;
   for (int i = 2; i <= n; i++)
       if (phi[i] == i)
           for (int j = i; j <= n; j += i)
               phi[j] = phi[j] / i * (i - 1);
} // 埃氏筛顺便得到 phi(i)
int main() {
   cin >> n;
   euler(n);
   for (int i = 2; i < n; i++) ans += phi[i];
   if (n == 1) puts("0");
   else cout << ((ans << 1) + 3) << endl;
   return 0;
}

当然,这样做的时间复杂度为 \(O(n \log \log n)\),而利用线性筛可以达到 \(O(n)\),核心思想就是:

\(p\) 为质数,若 \(p \mid n\)\(p^2 \mid n\),则 \(\varphi(n) = \varphi({n \over p}) \times p\)

\(p\) 为质数,若 \(p \mid n\)\(p^2 \nmid n\),则 \(\varphi(n) = \varphi({n \over p}) \times (p-1)\)

代码如下。

int v[MAXN], prime[MAXN], phi[MAXN];
void euler(int n) {
    // memset(v, 0, sizeof(v))
    // m = 0; // m 为质数数量
    for (int i = 2; i <= n; i++) {
        if (!v[i]) {prime[++m] = v[i] = i; phi[i] = i - 1;}
        for (int j = 1; j <= m; j++) {
            if (prime[j] > v[i] || i * prime[j] > n) break;
            v[i * prime[j]] = prime[j];
            phi[i * prime[j]] = phi[i] * (i % prime[j] ? prime[j] - 1 : prime[j]);
        }
    }
}

三、同余

\(a \bmod m = b \bmod m\),则称 \(a,b\)\(m\) 同余,记作 \(a \equiv b \pmod{m}\)

3.1 同余类与剩余系

前方一大堆恐怖芝士袭来!

对于任意 \([0, m - 1]\) 区间的 \(a\),集合 \(\{a+km\}(k \in \mathbb Z)\) 的所有数模 \(m\) 同余,余数都是 \(a\)。该集合称为一个模 \(m\)同余类,简记为 \(\overline{a}\)

\(m\) 的同余类一共有 \(m\) 个,分别为 \(\overline{0},\overline{1},\overline{2},\dots,\overline{m-1}\),它们构成 \(m\)完全剩余系

\(1\)\(m\) 中与 \(m\) 互质的数代表的同余类一共有 \(\phi(m)\) 个,它们构成 \(m\)简化剩余系(比如,模 \(18\) 的简化剩余为 \(\{\overline{1},\overline{5},\overline{7},\overline{11},\overline{13}\}\)

(形象化一点,\(\{1, 3, 5, 7, 9, \dots\}\) 的所有数模 \(2\) 同余,余数都是 \(1\)。)

简化剩余系关于模 \(m\) 乘法封闭。即若 \(a,b(1\leq a,b \leq m)\)\(m\) 互质,则 \(a \times b \bmod m\) 也属于 \(m\) 的简化剩余系。

3.2 费马小定理

\(p\) 是质数,则对于任意整数 \(a\),有 \(a^p \equiv a \pmod{p}\)

3.3 欧拉定理

若正整数 \(a,n\) 互质,则 \(a^{\varphi(n)} \equiv 1 \pmod{n}\)

欧拉定理的推论:

若正整数 \(a,n\) 互质,则对于任意正整数 \(b\),有 \(a^b \equiv a^{b \bmod \varphi(n)} \pmod n\)

例题 3.3.1 「高级算法」最幸运的数(POJ3696)

原题目链接:Link

显然,\(x\)\(8\) 连在一起形成的数就是 \(8 \times {(10^x - 1) \over 9}\)

(推论:\(x\)\(a\) 连在一起形成的数就是 \(a \times {(10^x - 1) \over 9}\)。)

那么,题目要求一个最小的 \(x\),满足 \(L \mid 8 \times {(10^x - 1) \over 9}\)

我们设 \(d = \gcd(L, 8)\),则

\(L \mid 8 \times {(10^x - 1) \over 9} \to 9L \mid 8 \times (10^x - 1) \to \frac{9L}{d} \mid 10^x - 1 \to 10^x \equiv 1(\bmod \frac{9L}{d})\)

我们知道,若正整数 \(a,n\) 互质,则满足 \(a^x \equiv 1 (\bmod n)\) 的最小正整数 \(x_0\)\(\varphi(n)\) 的因数(即 \(x_0 \mid \varphi(n)\))。所以,我们只要求出 \(\varphi({9L \over d})\) 的所有因数,再用快速幂检验即可。代码如下:

#include <bits/stdc++.h> // 各种 long long 开起来
using namespace std;
#define LL long long
#define ULL unsigned long long
#define PII pair<int, int>
#define M(x, y) make_pair(x, y)
const LL inf = 1e18;

LL L;
int tot;

LL phi(LL n) {
    LL ans = n;
    for (LL i = 2; i <= n / i; i++) {
        if (n % i == 0) {
            ans = ans / i * (i - 1);
            while (n % i == 0) n /= i;
        }
    }
    if (n > 1) ans = ans / n * (n - 1);
    return ans;
} // 求一个数的 phi,记得开 long long

LL gcd(LL x, LL y) {return y ? gcd(y, x % y) : x;} // 求 gcd,可以 __gcd 代替

LL qm(LL a, LL b, LL k) {
    LL ans = 0;
    while (b) {
        if (b & 1) ans = (ans + a) % k;
        a = (a + a) % k;
        b >>= 1;
    }
    return ans;
} // 龟速乘

LL q(LL a, LL b, LL k) {
    LL ans = 1;
    while (b) {
        if (b & 1) ans = qm(ans, a, k);
        a = qm(a, a, k);
        b >>= 1;
    }
    return ans;
} // 快速幂
int main() {
    while (scanf("%lld", &L) != EOF) {
        tot++;
        if (L == 0ll) return 0;
        int d = gcd(8, L); L = L * 9 / d;
        if (gcd(L, 10) > 1) {
            puts("0");
            continue;
        }
        LL k = phi(L), ans = inf;
        for (LL i = 1; i <= k / i; i++)
            if (k % i == 0) {
                if (q(10, i, L) == 1) {
                    ans = i;
                    break; // 一定是最小的
                }
                if (q(10, k / i, L) == 1) ans = min(ans, k / i); // 这个不一定,所以不能直接 break
            } // 枚举
        printf("%lld\n", ans);
    }
    return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM