P1082 [NOIP2012 提高組] 同餘方程 尤拉定理

尔一發表於2024-07-26

[NOIP2012 提高組] 同餘方程

解法

在這個問題中,我們想要找到 𝑥 使得ax≡1(modb)。根據尤拉定理,ab互質,得a^φ(b) ≡1(modb)。
先用尤拉φ(b),再求快速冪

為了應用尤拉定理,我們需要確認 a 和 b 是互質的,即 gcd(a,b)=1。如果 a 和 b 不是互質的,那麼同餘方程 ax ≡ 1(modb) 就沒有解。
假設 a 和 b 是互質的,根據尤拉定理,我們有:a^φ(b) ≡ 1(modb)
這是直接由尤拉定理給出的。這裡,φ(b) 是小於或等於 b 且與b 互質的正整數的個數。
如果我們有 a^φ(b) ≡ 1(modb),那麼我們可以將等式兩邊同時乘以 a^(−1)(a 在模 b 下的逆元):a^φ(b) ⋅a^(−1) ≡ 1⋅a^(−1) (modb)
由於 a^φ(b) ≡1(modb),我們可以簡化等式:1⋅a^(−1) ≡ a^(−1) (modb)
這裡 a^(−1) 就是 ax≡1(modb) 的解,因為:a⋅a^(−1) ≡1(modb)
所以,a^φ(b)≡1(modb) 實際上給出了 a 的逆元 a^(−1) 的存在性,而 a^(−1)就是 ax≡1(modb) 的解。

總結來說,尤拉定理直接告訴我們 a^φ(b)≡1(modb),而要得到 ax≡1(modb) 的解,我們只需要取 a^(φ(b)−1)作為 x,因為 a^(φ(b)−1)就是 a 的逆元。

題目描述

求關於 x 的同餘方程 ax≡1(modb) 的最小正整數解。

輸入格式

一行,包含兩個整數 a,b,用一個空格隔開。

輸出格式

一個整數 x0,即最小正整數解。輸入資料保證一定有解。

樣例 #1

樣例輸入 #1

3 10

樣例輸出 #1

7

提示

資料規模與約定

  • 對於 40% 的資料,2 ≤b≤ 1,000
  • 對於 60% 的資料,2 ≤b≤ 50,000,000;
  • 對於 100% 的資料,2 ≤a, b≤ 2,000,000,000。

程式碼

#include<iostream>
#include<map>
#include<vector>
#include<deque>
#include<algorithm>
#include<unordered_map>
#include<set>
#include<string>
using namespace std;
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define mm(a, b) memset(a, b, sizeof(a))
#define ll long long
#define mp make_pair
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10, mod = 1e9 + 7;

ll n;
ll a[N], dp[N];
unordered_map<int, int> primes;


ll gcd(ll a, ll b){
    return b ? gcd(b, a % b) : a;
}

ll lcm(ll a, ll b) {
    return a / gcd(a, b) * b;
}

ll yuehe(ll x) {
    primes.clear();
    int k = x;
    for (int i = 2; i <= x / i; i++)
        while (x % i == 0)
        {
            x /= i;
            primes[i]++;
        }

    if (x > 1) primes[x]++;

    ll res = 1;
    for (auto p : primes)
    {
        ll a = p.first, b = p.second;
        ll t = 1;
        while (b--) t = (t * a + 1) % mod;
        res = res * t % mod;
    }
    return res - k;
}

ll phi(ll x) {
    ll res = x;
    for (ll i = 2; i * i <= x; i++) {
        if (x % i == 0) {
            res = res / i * (i - 1);
            while (x % i == 0) x /= i;
        }
    }
    if (x > 1) res = res / x * (x - 1);
    return res;
}

ll qmi(ll a, ll b, ll p)
{
    ll res = 1 % p;
    while (b)
    {
        if (b & 1) res = res * a % p;
        a = a * (ll)a % p;
        b >>= 1;
    }
    return res;
}

void solve() {
    ll a, b;
    cin >> a >> b;
    if (gcd(a, b) != 1) return;
    ll p = phi(b);
    ll x = qmi(a, p - 1, b);
    cout << x;
}

int main() {
    ios;
    int t;
    //cin >> t;
    t = 1;
    while (t--) solve();
    return 0;
}

相關文章