# 「学习笔记」模运算与 BSGS 算法

## 取模

[5 mod 3 = 2\ 7 mod 4 = 3\ 3 mod 3 = 0\ ]

(x) 为被除数，(y) 为除数，(z) 为余数，则 (x = k cdot y + z, k = lfloor dfrac{x}{y} floor)

## 模运算

[left (a + b ight ) mod c = left (a mod c + b mod c ight ) mod c\ left (a - b ight ) mod c = left (a mod c - b mod c ight ) mod c\ left (a cdot b ight ) mod c = left [left (a mod c ight ) cdot left (b mod c ight ) ight ] mod c\ ]

(left ( n! ight ) mod p = left [ left ( n - 1 ight )! mod p imes n mod p ight] mod p)

``````#include <iostream>
using namespace std;

int n, p;

int main() {
cin >> n >> p;
int ans = 1;
for (int i = 1; i <= n; ++ i) {
ans = 1ll * ans * i % p;
}
cout << ans << endl;
return 0;
}
``````

## BSGS 算法

``````int solve(int a, int b, int p) {
// O(p)
int v = 1;
for (int x = 0; x <= p - 2; ++ x) {
if (v == b)    return x;
v = 1ll * v * a % p;
}
return -1;
}
``````

(a^{p - 1} mod p = 1) 可知，余数会在 (1) 处循环。

[a^{p - 1 + k} mod p\ egin{aligned} &= a^{p - 1} cdot a^k mod p\ &= a^k mod p end{aligned} ]

[a_0 quad a_1 quad a_2 cdots quad a^{s - 1}\ Downarrow (cdot a^s) Uparrow (div a^s)\ a^s quad a^{s + 1} quad a^{s + 2} cdots a^{2s - 1}\ a^2s quad a^{2s + 1} quad a^{2s + 2} cdots a^{3s - 1}\ ]

``````#include <set>
using namespace std;

int solve(int a, int b, int p) {
int s = sqrt(p);
int v = 1;
set<int> se;
for (int i = 0; i < s; ++ i) {
se.insert(v);
v = 1ll * v * a % p;
}
// O(p / s)
for (int i = 0; i * s <= p; ++ i) { // 看答案是否在第 i 行里面
// 要看 b * a (-is) 是否在第 0 行出现
int c = 1ll * b * qpow(qpow(a, i * s, p), p - 2, p) % p;
if (se.count(c) != 0) {
int v = qpow(a, i * s, p); // 第 i 行的第一个数
for (int j = i * s; ; ++ j) { // O(s)
if (v == b)    return j;
v = 1ll * v * a % p;
}
}
}
return -1;
}
``````