1 条题解
-
0
自动搬运
来自洛谷,原作者为

Weng_Weijie
やー!今日もパンがうまい!搬运于
2025-08-24 21:59:20,当前版本为作者最后更新于2018-03-28 19:42:22,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
显然将分解因数之后能得到,然后就能算出
所以这题的难点就在于如何分解因数,这里用到了Pollard rho算法
Pollard rho 算法原理:
生成一个随机数, 判断能否整除, 如果不能,那么继续由生成下一个,已知循环做下去,必定构成一个环,形状类似一个,所以叫Pollard rho算法
Pollard rho 算法流程 (注:2至6均在模意义下):
- 判断是否为质数,若是质数直接退出
- 随机一个和常数
- 令
- 令
- 重复执行4,直到或且
- 若那么重新从1开始执行
- 继续递归分解和
之后得到,之后剩余的就轻松解决了
代码如下
#include <stdio.h> #include <stdlib.h> #define int long long int e, N, c, d, n, r; //计算x,y的积 inline int mul(int x, int y, int c) { x %= c, y %= c; int r = 0; while (y) { if (y & 1) {r = r + x; if (r >= c) r -= c; } x = x + x; if (x >= c) x -= c; y = y >> 1; } return r; } //计算x的y次方 inline int pow(int x, int y, int c) { x %= c; int r = 1; while (y) { if (y & 1) r = mul(r, x, c); x = mul(x, x, c); y >>= 1; } return r; } int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } //求逆元 void exgcd(int a, int b, int &x, int &y) { if (!b) x = 1, y = 0; else { exgcd(b, a % b, y, x); y = (r + y - mul(a / b, x, r)) % r; } } //pollard rho算法 int pollard(int n, int c) { int x, y, d, i = 1, k = 2; x = 1LL * rand() * rand() % (n - 1) + 1; y = x; while (1) { x = (mul(x, x, n) + c) % n; d = gcd((x - y + n) % n, n); if (d > 1 && d < n) return d; if (x == y) return n; // x=y说明构成了一个环,说明选定的c不好,那么重新来一遍 if (++i == k) k <<= 1, y = x; // 由于y不一定在环内,所以随时更新y的值,不然会死循 } return 23333333; } int tmp; signed main() { signed x; srand(x); scanf("%lld%lld%lld", &e, &N, &c); int p = N; while (p >= N) p = pollard(N, 1LL * rand() * rand() % (n - 1) + 1); r = (p - 1) * (N / p - 1); exgcd(e, r, d, tmp); printf("%lld %lld\n", d, pow(c, d, N)); return 0; }
- 1
信息
- ID
- 3322
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者