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(); }
posted @ 2021-03-24 11:29  chenyilei  阅读(30)  评论(0编辑  收藏  举报