51Nod-1038-X^A Mod P
2017-09-28 19:42
148 查看
ACM模版
![](http://img.blog.csdn.net/20170928193915906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZl96eWo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
leader_win’s blog 讲得倒是十分详细,可是我依然懵逼着,数论真的恶心,太多太多╮(╯﹏╰)╭……
描述
题解
第一次接触原根这个玩意儿,感觉真恶心,一脸懵逼啊……leader_win’s blog 讲得倒是十分详细,可是我依然懵逼着,数论真的恶心,太多太多╮(╯﹏╰)╭……
代码
#include <cmath> #include <vector> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 100100; ll qk_pow(ll a, ll b, ll mod) { ll ret = 1; while (b) { if (b & 1) { ret = ret * a % mod; } b >>= 1; a = a * a % mod; } return ret; } ll ex_gcd(ll a, ll b, ll &x, ll &y) { if (b == 0) { x = 1; y = 0; return a; } else { ll r = ex_gcd(b, a % b, y, x); y -= x * (a / b); return r; } } vector<ll> a; bool check(ll g, ll p) { for (int i = 0; i < a.size(); i++) { if (qk_pow(g, (p - 1) / a[i], p) == 1) { return 0; } } return 1; } // 求解原根 ll primitive_root(ll p) { ll tmp = p - 1; for (int i = 2; i <= tmp / i; i++) { if (tmp % i == 0) { a.push_back(i); while (tmp % i == 0) { tmp /= i; } } } if (tmp != 1) { a.push_back(tmp); } ll g = 1; while (true) { if (check(g, p)) { return g; } ++g; } } struct sa { ll x; int id; bool operator < (const sa &b) const { if (x == b.x) { return id < b.id; } return x < b.x; } } rec[MAXN]; // 求解离散对数 ll discerte_log(ll x, ll n, ll m) { int s = (int)(sqrt((double)m + 0.5)); while ((ll)s * s <= m) { s++; } ll cur = 1; sa tmp; for (int i = 0; i < s; i++) { tmp.x = cur; tmp.id = i; rec[i] = tmp; cur = cur * x % m; } sort(rec, rec + s); ll mul = qk_pow(cur, m - 2, m) % m; cur = 1; for (int i = 0; i < s; i++) { ll more = n * cur % m; tmp.x = more; tmp.id = -1; int j = (int)(lower_bound(rec, rec + s, tmp) - rec); if (rec[j].x == more) { return i * s + rec[j].id; } cur = cur * mul % m; } return -1; } // 求解n次剩余 vector<ll> residue(ll p, ll n, ll a) { vector<ll> ret; if (a == 0) { ret.push_back(0); return ret; } ll g = primitive_root(p); ll m = discerte_log(g, a, p); if (m == -1) { return ret; } ll A = n, B = p - 1, C = m, x, y; ll G = ex_gcd(A, B, x, y); if (C % G != 0) { return ret; } x = x * (C / G) % B; ll delta = B / G; for (int i = 0; i < G; i++) { x = ((x + delta) % B + B) % B; ret.push_back(qk_pow(g, x, p)); } sort(ret.begin(), ret.end()); ret.erase(unique(ret.begin(), ret.end()), ret.end()); return ret; } ll P, A, B; int main() { int T; scanf("%d", &T); while (T--) { a.clear(); scanf("%lld%lld%lld", &P, &A, &B); vector<ll> ans; ans = residue(P, A, B); if (ans.empty()) { puts("No Solution"); } else { for (int i = 0; i < ans.size(); i++) { printf("%lld ", ans[i]); } putchar(10); } } return 0; }
相关文章推荐
- 51nod 1014 X^2 Mod P
- 1038 X^A Mod P
- 51NOD 1038:X^A Mod P——题解
- 51nod 1038 矩阵取数问题 (DP)
- 51nod 1038(n次剩余)
- 1080 两个数的平方和 分类: 51nod 2015-07-20 22:20 11人阅读
- 51Nod-斜率最大
- 51nod 1050 循环数组最大子段和
- SDNU 51nod 几道简单的博弈题目
- 51NOD 1099 任务执行顺序
- 51nod 1315 合法整数集
- 51nod 1174 区间中最大的数
- 51nod 1433 0和5
- 51nod 1215:数组的宽度 单调栈
- 51nod 1113 矩阵连乘快速幂模板 (对100000007取模)
- 51nod 1376 最长递增子序列的数量(dp、CDQ分治 | BIT)
- 51Nod - 1267 4个数和为0
- 51nod 1495 中国好区间
- 51nod 1105 第K大的数
- 51nod 1007 正整数分组 (类01背包问题)