2021.3.24
\(\mathcal{A}\)
bsgs别忘了等式右边b=0和同n不互质的情况。
\(\mathcal{B}\)
数论之神
#include <bits/stdc++.h>
using namespace std;
namespace cxcyl {
typedef long long ll;
const int inf = (int)1e9;
struct Hashmap {
static const int key = 999917, N = (int)5e5 + 5;
int fir[key], x[N], y[N], nxt[N], cnt, stk[N], top;
inline Hashmap() {}
inline void clear() { cnt = 0; while (top) fir[stk[top--]] = 0; }
inline void add(int a, int b) { x[++cnt] = b; y[cnt] = inf; nxt[cnt] = fir[a]; fir[a] = cnt; }
inline int count(int idx) {
int u = idx % key;
for (int e = fir[u]; e; e = nxt[e])
if (x[e] == idx)
return 1;
return 0;
}
inline int &operator [](int idx) {
int u = idx % key;
for (int e = fir[u]; e; e = nxt[e])
if (x[e] == idx)
return y[e];
add(u, idx), stk[++top] = u; return y[cnt];
}
} s;
int fac[100][2], cnt;
int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); }
inline int fpow_r(int a, int b) {
int ret = 1;
for (; b; b >>= 1, a = a * a)
if (b & 1)
ret = ret * a;
return ret;
}
inline int fpow(int a, int b, int mod) {
int ret = 1;
for (; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1)
ret = 1ll * ret * a % mod;
return ret;
}
inline int phi(int n) {
int m = n;
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) {
while (n % i == 0) n /= i;
m -= m / i;
}
if (n > 1) m -= m / n;
return m;
}
inline int gen(int p) {
int x = phi(p);
for (int i = 2; ; ++i) {
bool flag = 1;
for (int j = 2; j * j < x && flag; ++j)
if (x % j == 0) {
if (fpow(i, j, p) == 1) flag = 0;
if (fpow(i, x / j, p) == 1) flag = 0;
}
if (flag) return i;
}
}
inline void getfac(int n) {
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) {
fac[++cnt][0] = i;
while (n % i == 0) n /= i, ++fac[cnt][1];
}
if (n > 1) {
fac[++cnt][0] = n;
fac[cnt][1] = 1;
}
}
inline int bsgs(int a, int b, int c) {
assert(gcd(a, c) == 1);
s.clear();
int n = ceil(sqrt(c)), x = 1, ret = 1e9, o = phi(c);
for (int i = 0; i <= n; ++i) {
s[x] = min(s[x], i);
if (i < n) x = 1ll * x * a % c;
}
for (int i = 0, y = 1; i <= n; ++i, y = 1ll * y * x % c) {
int t = 1ll * b * fpow(y, o - 1, c) % c;
if (s.count(t)) ret = min(ret, s[t] + i * n);
}
return ret < 1e9 ? ret : -1;
}
inline ll exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) { x = 1; y = 0; return a; }
ll ret = exgcd(b, a % b, y, x);
y -= a / b * x;
return ret;
}
inline int main() {
int T;
scanf("%d", &T);
while (T--) {
cnt = 0;
memset(fac, 0, sizeof(fac));
//clear
int A, B, k;
scanf("%d%d%d", &A, &B, &k);
getfac(2 * k + 1);
int ans = 1;
for (int i = 1; i <= cnt; ++i) {
int u = fpow_r(fac[i][0], fac[i][1]), g = gen(u), a = A, b = B;
if (b % u == 0)
ans = ans * fpow_r(fac[i][0], fac[i][1] - ceil((double)fac[i][1] / a));
else {
int d = gcd(b, u);
if (d > 1) {
b /= d;
u /= d;
int cnt = 0;
while (d > 1) {
d /= fac[i][0];
++cnt;
}
if (cnt % a) ans = 0;
else ans = ans * fpow_r(fac[i][0], cnt - cnt / a);
}
int b0 = bsgs(g, b, u), o = phi(u);
ll x, y, l = exgcd(a, o, x, y);
if (b0 % l) ans = 0;
else {
ll r = o / l;
x = (x * b0 / l % r + r) % r;
ans = ans * ((o - 1 - x) / r + 1);
}
}
}
printf("%d\n", ans);
}
return 0;
}
} int main() { return cxcyl::main(); }
Fib数列
由通项列方程:\(t - \frac{1}{t} \equiv \sqrt{5}N(mod p), t = (\frac{\sqrt{5}+1}{2})^{n}\),用求根公式用几次二次剩余求解。
#include <bits/stdc++.h>
using namespace std;
namespace cxcyl {
const int inf = (int)1e9, mod = (int)1e9 + 9, inv2 = mod + 1 >> 1;
int N, ans[2] = {inf, inf}, s5;
struct Com {
static int sqr;
int re, im;
inline Com(int x = 0, int y = 0) : re(x), im(y) {}
inline Com operator *(const Com &rhs) {
return Com((1ll * re * rhs.re + 1ll * im * rhs.im % mod * sqr) % mod, (1ll * re * rhs.im + 1ll * im * rhs.re) % mod);
}
};
int Com::sqr;
template<typename T> inline int chkmin(T &x, T y) { return x > y ? x = y, 1 : 0; }
inline int fpow(int a, int b) {
int ret = 1;
for (; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1)
ret = 1ll * ret * a % mod;
return ret;
}
inline Com fpow(Com a, int b) {
Com ret(1, 0);
for (; b; b >>= 1, a = a * a)
if (b & 1)
ret = ret * a;
return ret;
}
inline int mod_sqrt(int x) {
if (fpow(x, mod - 1 >> 1) != 1) return -1;
int a = rand();
while (fpow(((1ll * a * a - x) % mod + mod) % mod, mod - 1 >> 1) == 1) a = rand();
Com::sqr = ((1ll * a * a - x) % mod + mod) % mod;
return (fpow(Com(a, 1), mod + 1 >> 1).re + mod) % mod;
}
inline pair<int, int> bsgs(int a, int b, int c) {
map<int, int> s[2];
int n = ceil(sqrt(c)), x = 1, ret[2] = {inf, inf};
for (int i = 0; i <= n; ++i) {
if (s[i & 1].find(x) == s[i & 1].end() || s[i & 1][x] > i) s[i & 1][x] = i;
if (i < n) x = 1ll * x * a % c;
}
for (int i = 0, y = 1; i <= n; ++i, y = 1ll * y * x % c) {
int t = 1ll * b * fpow(y, c - 2) % c;
if (s[0].find(t) != s[0].end()) chkmin(ret[(i * n + s[0][t]) & 1], i * n + s[0][t]);
if (s[1].find(t) != s[1].end()) chkmin(ret[(i * n + s[1][t]) & 1], i * n + s[1][t]);
}
return make_pair(ret[0], ret[1]);
}
inline void work(int you, int d) {
you = (you + mod) % mod;
pair<int, int> ret = bsgs((1ll + s5) * inv2 % mod, you, mod);
if (d == 0) ans[0] = min(ans[0], ret.first);
else ans[1] = min(ans[1], ret.second);
}
inline int main() {
scanf("%d", &N);
s5 = mod_sqrt(5);
int tmp0 = (5ll * N * N - 4) % mod, tmp1 = (5ll * N * N + 4) % mod;
int ret = mod_sqrt(tmp0);
if (ret != -1) {
work((1ll * s5 * N + ret) % mod * inv2 % mod, 1);
work((1ll * s5 * N - ret) % mod * inv2 % mod, 1);
}
ret = mod_sqrt(tmp1);
if (ret != -1) {
work((1ll * s5 * N + ret) % mod * inv2 % mod, 0);
work((1ll * s5 * N - ret) % mod * inv2 % mod, 0);
}
if (ans[0] == 1e9 && ans[1] == 1e9) puts("-1");
else printf("%d\n", min(ans[0], ans[1]));
return 0;
}
} int main() { return cxcyl::main(); }