题意
分析
- 这里分几种情况来分析:当 时, 要么等于 ,要么等于 ,直接判断即可;当 时, 为等差数列,通项公式为 ,于是求解同余方程 即可。
- 最后一种情况,当 时,根据高中的一些知识我们可以知道,这个是可以转化成一个等比数列的。待定系数 有 ,解得 。令 ,那么 。因此原问题转化为关于 的同余方程 是否有解和最小正整数解的问题了。这是离散对数问题,利用大步小步算法求解即可。
大步小步算法(BSGS)
- 用于求解形如方程 的离散对数问题,其基于 meet-in-the-middle 的思想,复杂度 。
- 首先因为 ,所以如果原方程有解,则在 的范围也一定有解。
- 我们拆分 ,令 ,则一定存在 使得 。此时方程转化为求解 满足
- 根据这个式子,我们先预处理出 中的所有值,然后对于每一个 计算出 并判断是否在集合 中即可。
代码
| #include <bits/stdc++.h> |
| #define int long long |
| #define inf 1e10 |
| using namespace std; |
| int a, b, s, g, p; |
| int A, B, C; |
| |
| inline void read(int &x) { |
| char ch = x = 0; |
| int m = 1; |
| while (ch < '0' || ch > '9') ch = getchar(); |
| while (ch >= '0' && ch <= '9') { |
| x = (x << 1) + (x << 3) + ch - 48; |
| ch = getchar(); |
| } |
| x *= m; |
| return ; |
| } |
| |
| inline void print(int x) { |
| if (x < 0) putchar('-'), x = -x; |
| static int stk[50]; |
| int top = 0; |
| do { |
| stk[top++] = x % 10; |
| x /= 10; |
| } while (x); |
| while (top) { |
| putchar(stk[--top] + 48); |
| } |
| putchar('\n'); |
| return ; |
| } |
| |
| inline int ksmi(int a, int b, int p) { |
| a %= p; |
| int res = 1; |
| while (b) { |
| if (b & 1) res = res * a % p; |
| a = a * a % p; |
| b >>= 1; |
| } |
| return res; |
| } |
| |
| inline int BSGS(int a, int b, int p) { |
| a %= p, b %= p; |
| if (b == 1 || a == b) return b != 1; |
| map<int, int> mp; |
| int B = ceil(sqrt(p)), res = inf; |
| for (int i = B; i; i--) { |
| mp[ksmi(a, i * B, p)] = i * B; |
| } |
| for (int i = 0; i <= B; i++) { |
| if (mp.find(b * ksmi(a, i, p) % p) != mp.end()) { |
| res = min(res, mp[b * ksmi(a, i, p) % p] - i); |
| } |
| } |
| if (res == inf) { |
| return -1; |
| } else { |
| return res; |
| } |
| } |
| |
| signed main() { |
| int T; |
| read(T); |
| while (T--) { |
| read(p), read(a), read(b), read(s), read(g); |
| if (s == g) print(0); |
| else if (a == 0) { |
| if (b == g) print(1); |
| else print(-1); |
| } else if (a == 1) { |
| if (b == 0) print(-1); |
| else { |
| int x = ((g - s) % p + p) % p * ksmi(b, p - 2, p) % p; |
| print(x); |
| } |
| } else if (s == 0 && b == 0) { |
| print(-1); |
| } else { |
| A = a, C = ksmi(A - 1, p - 2, p) * b % p; |
| B = ksmi(s + C, p - 2, p) * ((g + C) % p) % p; |
| print(BSGS(A, B, p)); |
| } |
| } |
| return 0; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话