同余方程 A^x = B (mod C)的解 - BSGS/exBSGS - 洛谷BSGS题单
作者:互联网
文章目录
这波不写详解了,OI-Wiki有详解。
思路其实很简单,先用hash表存一部分计算结果,然后枚举另一半,同时查找是否存在解。
模板
inline ll mul(ll a, ll b, ll p) { return (a * b - (ll)((long double)a / p * b) * p + p) % p; }
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = mul(x, x, mod)) if (m & 1) res = mul(res, x, mod);
return res;
}
inline void exgcd(ll a, ll b, ll &g, ll &x, ll &y) {
if (b) exgcd(b, a % b, g, y, x), y -= a / b * x;
else x = 1, y = 0, g = a;
}
inline ll inv(ll x, ll m) {
ll a, b, g;
exgcd(x, m, g, a, b);
return (a % m + m) % m;
}
map<ll, ll> bs;
inline ll BSGS(ll a, ll b, ll p) { // (a, p) = 1
if (b == 1 || p == 1) return 0;
ll m = sqrt(p) + 1; bs.clear();
for (ll k = 0, t = b; k <= m; k ++, t = mul(t, a, p)) bs[t] = k;
for (ll x = 1, t = qpow(a, m, p), base = t; x <= m; x ++, t = mul(t, base, p))
if (bs.count(t)) return ((x * m - bs[t]) % p + p) % p;
return -1;
}
inline ll exBSGS(ll a, ll b, ll c) {
a %= c, b %= c;
if (b == 1 || c == 1) return 0;
ll g = __gcd(a, c), k = 0, t = 1, res;
while (g ^ 1LL) {
if (b % g) return -1;
c /= g, b /= g, t = mul(t, (a / g), c), k ++;
if (t == b) return k;
g = __gcd(a, c);
}
b = b * inv(t, c) % c, res = BSGS(a, b, c);
return ~res ? res + k : res;
}
题目(来自洛谷的BSGS题单)
然鹅,本蒟蒻会写的题过于模板。。。
[TJOI2007] 可爱的质数/【模板】BSGS
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define fast ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define fin freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld nd << 1
#define rd nd << 1 | 1
typedef vector<int> vec;
// typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128_t i128;
// const int mod = 1e9 + 7;
// const int mod = 998244353;
const int maxn = 1e6 + 50;
const int inf = 0x3f3f3f3f; // 1e9;
const ll INF = 0x3f3f3f3f3f3f3f3f; // 1e18;
ll n, b, p;
map<ll, int> bsgs;
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = x * x % mod) if (m & 1) res = res * x % mod;
return res;
}
int main() {
scanf("%lld%lld%lld", &p, &b, &n);
int m = sqrt(p) + 1;
for (ll k = 0, t = n % p; k <= m; k ++, t = t * b % p) bsgs[t] = k;
for (ll x = 1, t = qpow(b, m, p), base = t; x <= m; x ++, t = t * base % p)
if (bsgs.count(t)) printf("%lld\n", x * m - bsgs[t]), exit(0);
return cout << "no solution", 0;
}
[SDOI2011]计算器
全是板子。。。
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define fast ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define fin freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld nd << 1
#define rd nd << 1 | 1
typedef vector<int> vec;
// typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128_t i128;
// const int mod = 1e9 + 7;
// const int mod = 998244353;
const int maxn = 1e6 + 50;
const int inf = 0x3f3f3f3f; // 1e9;
const ll INF = 0x3f3f3f3f3f3f3f3f; // 1e18;
int T, op;
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = x * x % mod) if (m & 1) res = res * x % mod;
return res;
}
inline void exgcd(ll a, ll b, ll &g, ll &x, ll &y) {
if (b) {
exgcd(b, a % b, g, x, y);
swap(x, y), y -= a / b * x;
} else {
x = 1, y = 0, g = a;
}
}
inline ll inv(ll x, ll m) {
ll a, b, g;
exgcd(x, m, g, a, b);
return (a % m + m) % m;
}
map<ll, ll> bs;
ll bsgs(ll a, ll b, ll c) {
if (b == 1 || c == 1) return 0;
ll g = __gcd(a, c), k = 0, t = 1;
while (g ^ 1LL) {
if (b % g) return -1;
c /= g, b /= g, t = t * (a / g) % c, k ++;
if (t == b) return k;
g = __gcd(a, c);
}
b = b * inv(t, c) % c;
ll m = sqrt(c) + 1; bs.clear();
for (ll k = 0, t = b; k <= m; k ++, t = t * a % c) bs[t] = k;
for (ll x = 1, t = qpow(a, m, c), base = t; x <= m; x ++, t = t * base % c)
if (bs.count(t)) return ((x * m - bs[t]) % c + c) % c + k;
return -1;
}
int main() {
ll y, z, p, ans = 1;
scanf("%d %d", &T, &op);
switch (op) {
case 1: {
while (T -- ) {
scanf("%lld%lld%lld", &y, &z, &p);
printf("%lld\n", qpow(y % p, z, p));
}
}; break;
case 2: {
while (T -- ) {
scanf("%lld%lld%lld", &y, &z, &p);
ll g, a, b; exgcd(y, p, g, a, b);
if (z % g) puts("Orz, I cannot find x!");
else printf("%lld\n", (a * (z / g) % p + p) % p);
}
}; break;
case 3: {
while (T -- ) {
scanf("%lld%lld%lld", &y, &z, &p);
ans = bsgs(y % p, z % p, p);
if (ans == -1) puts("Orz, I cannot find x!");
else printf("%lld\n", ans);
}
}; break;
}
return 0;
}
多少个1?
等比求个和,变板子了
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define fast ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define fin freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld nd << 1
#define rd nd << 1 | 1
typedef vector<int> vec;
// typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128_t i128;
// const int mod = 1e9 + 7;
// const int mod = 998244353;
const int maxn = 1e6 + 50;
const int inf = 0x3f3f3f3f; // 1e9;
const ll INF = 0x3f3f3f3f3f3f3f3f; // 1e18;
int T, op;
inline ll mul(ll a, ll b, ll mod, ll res = 0) {
for ( ; b; b >>= 1, a = (a + a) % mod) if (b & 1) res = (res + a) % mod;
return res;
}
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = mul(x, x, mod)) if (m & 1) res = mul(res, x, mod);
return res;
}
inline void exgcd(ll a, ll b, ll &g, ll &x, ll &y) {
if (b) {
exgcd(b, a % b, g, x, y);
swap(x, y), y -= a / b * x;
} else {
x = 1, y = 0, g = a;
}
}
inline ll inv(ll x, ll m) {
ll a, b, g;
exgcd(x, m, g, a, b);
return (a % m + m) % m;
}
map<ll, ll> bs;
ll bsgs(ll a, ll b, ll c) {
if (b == 1 || c == 1) return 0;
/* ll g = __gcd(a, c), k = 0, t = 1;
while (g ^ 1LL) {
if (b % g) return -1;
c /= g, b /= g, t = mul(t, (a / g), c), k ++;
if (t == b) return k;
g = __gcd(a, c);
}
b = b * inv(t, c) % c; */
ll m = sqrt(c) + 1; bs.clear();
for (ll k = 0, t = b; k <= m; k ++, t = mul(t, a, c)) bs[t] = k;
for (ll x = 1, t = qpow(a, m, c), base = t; x <= m; x ++, t = mul(t, base, c))
if (bs.count(t)) return ((x * m - bs[t]) % c + c) % c;
return -1;
}
int main() {
ll k, m, ans;
scanf("%lld %lld", &k, &m);
ans = bsgs(10LL % m, (9LL * k + 1LL) % m, m);
printf("%lld", ans);
return 0;
}
[SDOI2013] 随机数生成器
特判,特判,特判!!!
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define fast ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define fin freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld nd << 1
#define rd nd << 1 | 1
typedef vector<int> vec;
// typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128_t i128;
// const int mod = 1e9 + 7;
// const int mod = 998244353;
const int maxn = 1e6 + 50;
const int inf = 0x3f3f3f3f; // 1e9;
const ll INF = 0x3f3f3f3f3f3f3f3f; // 1e18;
int T, op;
/* inline ll mul(ll a, ll b, ll mod, ll res = 0) {
for ( ; b; b >>= 1, a = (a + a) % mod) if (b & 1) res = (res + a) % mod;
return res;
} */
inline ll mul(ll a, ll b, ll mod) { return a * b % mod; }
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = mul(x, x, mod)) if (m & 1) res = mul(res, x, mod);
return res;
}
inline void exgcd(ll a, ll b, ll &g, ll &x, ll &y) {
if (b) {
exgcd(b, a % b, g, x, y);
swap(x, y), y -= a / b * x;
} else {
x = 1, y = 0, g = a;
}
}
inline ll inv(ll x, ll m) {
ll a, b, g;
exgcd(x, m, g, a, b);
return (a % m + m) % m;
}
map<ll, ll> bs;
ll bsgs(ll a, ll b, ll c) {
if (b == 1 || c == 1) return 0;
/* ll g = __gcd(a, c), k = 0, t = 1;
while (g ^ 1LL) {
if (b % g) return -1;
c /= g, b /= g, t = mul(t, (a / g), c), k ++;
if (t == b) return k;
g = __gcd(a, c);
}
b = b * inv(t, c) % c; */
ll m = sqrt(c) + 1; bs.clear();
for (ll k = 0, t = b; k <= m; k ++, t = mul(t, a, c)) bs[t] = k;
for (ll x = 1, t = qpow(a, m, c), base = t; x <= m; x ++, t = mul(t, base, c))
if (bs.count(t)) return ((x * m - bs[t]) % c + c) % c;
return -1;
}
int main() {
ll p, a, b, x1, t, ans;
scanf("%d", &T);
while (T -- ) {
scanf("%lld%lld%lld%lld%lld", &p, &a, &b, &x1, &t);
if (x1 == t) {
puts("1");
continue;
}
if (a == 0LL) {
if (b == t) puts("2");
else puts("-1");
continue;
}
if (a == 1LL) {
if (b == 0) puts("-1");
else {
ans = qpow(b, p - 2, p) * ((t - x1) % p + p) % p;
printf("%lld\n", ans + 1);
}
continue;
}
ll u = (t * (a - 1) + b) % p;
ll d = (x1 * (a - 1) + b) % p;
ans = bsgs(a, u * qpow(d, p - 2, p) % p, p);
if (ans == -1) puts("-1");
else printf("%lld\n", ans + 1);
}
return 0;
}
【模板】扩展 BSGS/exBSGS
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define fast ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define fin freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld nd << 1
#define rd nd << 1 | 1
typedef vector<int> vec;
// typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128_t i128;
// const int mod = 1e9 + 7;
// const int mod = 998244353;
const int maxn = 1e6 + 50;
const int inf = 0x3f3f3f3f; // 1e9;
const ll INF = 0x3f3f3f3f3f3f3f3f; // 1e18;
int T;
inline ll lcm(ll a, ll b) { return a / __gcd(a, b) * b; }
/* inline ll mul(ll a, ll b, ll mod, ll res = 0) {
for ( ; b; b >>= 1, a = (a + a) % mod) if (b & 1) res = (res + a) % mod;
return res;
} */
inline ll mul(ll a, ll b, ll mod) { return a * b % mod; }
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = mul(x, x, mod)) if (m & 1) res = mul(res, x, mod);
return res;
}
inline void exgcd(ll a, ll b, ll &g, ll &x, ll &y) {
if (b) exgcd(b, a % b, g, y, x), y -= a / b * x;
else x = 1, y = 0, g = a;
}
inline ll inv(ll x, ll m) {
ll a, b, g;
exgcd(x, m, g, a, b);
return (a % m + m) % m;
}
map<ll, ll> bs;
inline ll BSGS(ll a, ll b, ll p) { // (a, p) = 1
if (b == 1 || p == 1) return 0;
ll m = sqrt(p) + 1; bs.clear();
for (ll k = 0, t = b; k <= m; k ++, t = mul(t, a, p)) bs[t] = k;
for (ll x = 1, t = qpow(a, m, p), base = t; x <= m; x ++, t = mul(t, base, p))
if (bs.count(t)) return ((x * m - bs[t]) % p + p) % p;
return -1;
}
inline ll exBSGS(ll a, ll b, ll c) {
a %= c, b %= c;
if (b == 1 || c == 1) return 0;
ll g = __gcd(a, c), k = 0, t = 1, res;
while (g ^ 1LL) {
if (b % g) return -1;
c /= g, b /= g, t = mul(t, (a / g), c), k ++;
if (t == b) return k;
g = __gcd(a, c);
}
b = b * inv(t, c) % c, res = BSGS(a, b, c);
return ~res ? res + k : res;
}
ll a, b, p, ans;
int main() {
while (~scanf("%lld%lld%lld", &a, &p, &b) && (a || b || p)) {
if (~(ans = exBSGS(a, b, p))) printf("%lld\n", ans);
else puts("No Solution");
}
return 0;
}
【XR-1】快乐肥宅
BSGS求出特解(可能无解或者为唯一解),再用CRT合并答案即可(可能会爆long long)。
好毒瘤,枯了,先咕了。
[CQOI2018]破解D-H协议
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define fast ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define fin freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld nd << 1
#define rd nd << 1 | 1
typedef vector<int> vec;
// typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128_t i128;
// const int mod = 1e9 + 7;
// const int mod = 998244353;
const int maxn = 1e6 + 50;
const int inf = 0x3f3f3f3f; // 1e9;
const ll INF = 0x3f3f3f3f3f3f3f3f; // 1e18;
int T;
inline ll lcm(ll a, ll b) { return a / __gcd(a, b) * b; }
/* inline ll mul(ll a, ll b, ll mod, ll res = 0) {
for ( ; b; b >>= 1, a = (a + a) % mod) if (b & 1) res = (res + a) % mod;
return res;
} */
inline ll mul(ll a, ll b, ll p) { return (a * b - (ll)((long double)a / p * b) * p + p) % p; }
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = mul(x, x, mod)) if (m & 1) res = mul(res, x, mod);
return res;
}
inline void exgcd(ll a, ll b, ll &g, ll &x, ll &y) {
if (b) exgcd(b, a % b, g, y, x), y -= a / b * x;
else x = 1, y = 0, g = a;
}
inline ll inv(ll x, ll m) {
ll a, b, g;
exgcd(x, m, g, a, b);
return (a % m + m) % m;
}
map<ll, ll> bs;
inline ll BSGS(ll a, ll b, ll p) { // (a, p) = 1
if (b == 1 || p == 1) return 0;
ll m = sqrt(p) + 1; bs.clear();
for (ll k = 0, t = b; k <= m; k ++, t = mul(t, a, p)) bs[t] = k;
for (ll x = 1, t = qpow(a, m, p), base = t; x <= m; x ++, t = mul(t, base, p))
if (bs.count(t)) return ((x * m - bs[t]) % p + p) % p;
return -1;
}
inline ll exBSGS(ll a, ll b, ll c) {
a %= c, b %= c;
if (b == 1 || c == 1) return 0;
ll g = __gcd(a, c), k = 0, t = 1, res;
while (g ^ 1LL) {
if (b % g) return -1;
c /= g, b /= g, t = mul(t, (a / g), c), k ++;
if (t == b) return k;
g = __gcd(a, c);
}
b = b * inv(t, c) % c, res = BSGS(a, b, c);
return ~res ? res + k : res;
}
ll g, p, A, B, K;
int main() {
scanf("%lld%lld%d", &g, &p, &T);
while (T -- ) {
scanf("%lld%lld", &A, &B);
ll a = exBSGS(g, A, p), b = exBSGS(g, B, p);
printf("%lld\n", qpow(qpow(g, a, p), b, p));
}
return 0;
}
CF1106F Lunar New Year and a Recursive Sequence
用离散对数将表达式转换成一个线性方程,显然先求原根,再矩阵快速幂就好了。
// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include <bits/stdc++.h>
using namespace std;
#define fast ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define fin freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld nd << 1
#define rd nd << 1 | 1
typedef vector<int> vec;
// typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128_t i128;
// const int mod = 1e9 + 7;
const int mod = 998244353;
const int maxn = 1e6 + 50;
const int inf = 0x3f3f3f3f; // 1e9;
const ll INF = 0x3f3f3f3f3f3f3f3f; // 1e18;
int T;
inline ll lcm(ll a, ll b) { return a / __gcd(a, b) * b; }
/* inline ll mul(ll a, ll b, ll mod, ll res = 0) {
for ( ; b; b >>= 1, a = (a + a) % mod) if (b & 1) res = (res + a) % mod;
return res;
} */
inline ll mul(ll a, ll b, ll p) { return (a * b - (ll)((long double)a / p * b) * p + p) % p; }
inline ll qpow(ll x, ll m, ll mod, ll res = 1) {
for ( ; m; m >>= 1, x = mul(x, x, mod)) if (m & 1) res = mul(res, x, mod);
return res;
}
inline void exgcd(ll a, ll b, ll &g, ll &x, ll &y) {
if (b) exgcd(b, a % b, g, y, x), y -= a / b * x;
else x = 1, y = 0, g = a;
}
inline ll inv(ll x, ll m) {
ll a, b, g;
exgcd(x, m, g, a, b);
return (a % m + m) % m;
}
map<ll, ll> bs;
inline ll BSGS(ll a, ll b, ll p) { // (a, p) = 1
if (b == 1 || p == 1) return 0;
ll m = sqrt(p) + 1; bs.clear();
for (ll k = 0, t = b; k <= m; k ++, t = mul(t, a, p)) bs[t] = k;
for (ll x = 1, t = qpow(a, m, p), base = t; x <= m; x ++, t = mul(t, base, p))
if (bs.count(t)) return ((x * m - bs[t]) % p + p) % p;
return -1;
}
inline ll exBSGS(ll a, ll b, ll c) {
a %= c, b %= c;
if (b == 1 || c == 1) return 0;
ll g = __gcd(a, c), k = 0, t = 1, res;
while (g ^ 1LL) {
if (b % g) return -1;
c /= g, b /= g, t = mul(t, (a / g), c), k ++;
if (t == b) return k;
g = __gcd(a, c);
}
b = b * inv(t, c) % c, res = BSGS(a, b, c);
return ~res ? res + k : res;
}
int k;
ll n, m;
ll base[105][105], ans[105][105], tmp[105][105], a[105];
inline void mat_mul(int op, ll p) {
switch(op) {
case 1: {
memset(tmp, 0, sizeof tmp);
for (int i = 1; i <= k; i++)
for (int j = 1; j <= k; j++)
for (int o = 1; o <= k; o++)
tmp[i][j] = (tmp[i][j] + base[i][o] * base[o][j] % p) % p;
memcpy(base, tmp, sizeof tmp);
}; break;
case 2: {
memset(tmp, 0, sizeof tmp);
for (int i = 1; i <= k; i++)
for (int j = 1; j <= k; j++)
for (int o = 1; o <= k; o++)
tmp[i][j] = (tmp[i][j] + ans[i][o] * base[o][j] % p) % p;
memcpy(ans, tmp, sizeof tmp);
};break;
}
}
void mat_pow(ll ind, ll p) {
while (ind) {
if (ind & 1) mat_mul(2, p);
mat_mul(1, p), ind >>= 1;
}
}
int main() {
scanf("%d", &k);
for (int i = 1; i <= k; i++) scanf("%lld", &base[1][i]), ans[i][i] = 1LL;
for (int i = 2; i <= k; i++) base[i][i - 1] = 1LL;
scanf("%lld %lld", &n, &m);
mat_pow(n - k, mod - 1);
ll t = exBSGS(3, m, mod) % (mod - 1);
// cout << t << '\n';
ll g, x, y; exgcd(ans[1][1], mod - 1, g, x, y);
if (t % g) puts("-1");
else printf("%lld", qpow(3, mul(t / g, (x % (mod - 1) + mod - 1) % (mod - 1), mod - 1), mod));
return 0;
}
标签:洛谷,int,res,exBSGS,return,mod,BSGS,ll,define 来源: https://blog.csdn.net/qq_41743740/article/details/118946068