咱們知道 \((512 / 8) % 13 = 64 % 13 = 12\),顯然他是不遵循 \((512 \% 13) / (8 \% 13)\) 的,所以這裏就要用到逆元了。
逆元的定義 \(a * b \equiv 1 (mod\ p)\),a,p互質 b 就是 a 的逆元。
同時有 \(a * b + p * c \equiv 1 (mod\ p)\)ios
這個過程也就彷佛求解方程 \(a * x + b * y = 1\) 的過程, 可是有一個要注意的就是要保證最後求得的 x 是要大於0的,
也就是要對最後求得的 x 進行 x = (x % b + b) % b 一步操做。c++
/* Code by lifehappy 2020:04:23 */ #include<iostream> using namespace std; int exgcd(int a, int b, int &x, int &y) { if(!b) { x = 1; y = 0; return a; } int gcd = exgcd(b, a % b, x, y); int t = x; x = y; y = t - a / b * y; return gcd; } int main() { int a, b, x, y; while(cin >> a >> b) { exgcd(b, 13, x, y); x = (x % 13 + 13) % 13; printf("%d\n", (a * x) % 13); } return 0; }
關於費馬小定理的正確性這裏就不證實了。app
咱們知道,假設p是一個質數 \(a ^ {p-1} \equiv 1 (mod\ p)\)
一樣的咱們就能夠獲得 \(a ^ {p-2} \equiv a ^ {-1} (mod\ p)\)
因此其核心咱們就能夠變成一個快速冪了。ui
/* Code by lifehappy 2020:04:23 */ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; ll quick_pow(ll b, ll n) { ll ans = 1, po = b; while(n) { if(n & 1) ans = (ans * po) % mod; po = (po * po) % mod; n >>= 1; } return ans; } int main() { ll a, b; while(cin >> a >> b) {//計算(a / b) % mod; b = quick_pow(b, mod - 2); cout << (a * b) % mod << endl; } return 0; }
咱們先假定 \(p = k * i + j\ 1 < i < p, j < i\)spa
咱們能夠獲得\(p = k * i + j \equiv 0(mod\ p)\)code
對兩邊同時乘以\(i ^ {-1}, j ^ {-1}\)blog
獲得\(k * j ^ {-1} + i ^ {-1} \equiv 0(mod\ p)\)ci
有\(i ^ {-1} \equiv -k * j {-1}\)it
由於j < i 咱們能夠經過這個遞推關係獲得io
\(a[i] = -(p / i) * a[p % i]\)從而的到(1 ~ n)的逆元。
在此以前咱們還得知道$1 ^{-1} \equiv 1(mod\ p)
/* Code by lifehappy 2020:04:23 */ #include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N = 1e3 + 10, mod = 1e9 + 7; ll a[N]; int main() { a[1] = 1; for(ll i = 2; i < N; i++) { a[i] = -(mod / i) * a[mod % i]; a[i] = (a[i] % mod + mod) % mod; } for(int i = 1; i <= 10; i++) printf("%lld %lld\n", a[i], ((long long)i * a[i]) % mod); return 0; }
上面代碼運行狀況