數學知識學習筆記


數學知識學習筆記

一、質數

略。

二、歐拉函數

\(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