[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;
}