bzoj 1420 Discrete Root - 原根 - exgcd - BSGS

题目传送门

  戳我来传送

题目大意

  给定$k, p, a$,求$x^{k}\equiv a \pmod{p}$在模$p$意义下的所有根。

  考虑模$p$下的某个原根$g$。

  那么$x  = g^{ind_{g}x}, a = g^{ind_{g}a}$。

  所以原方程转化为$g^{k\cdot ind_{g}x}\equiv g^{ind_{g}a} \pmod{p}$。

  所以方程等价于$k\cdot ind_{g}x \equiv ind_{g}a \pmod{\varphi(p)}$。

  用exgcd解出$ind_{g}x$的所有可能的解,再用快速幂算出$x$即可。

Code

  1 /**
  2  * bzoj     
  3  * Problem#1420
  4  * Accepted
  5  * Time: 44ms
  6  * Memory: 2032k 
  7  */
  8 #include <bits/stdc++.h>
  9 #include <ext/pb_ds/hash_policy.hpp>
 10 #include <ext/pb_ds/assoc_container.hpp>
 11 using namespace std;
 12 using namespace __gnu_pbds;
 13 typedef bool boolean;
 14 
 15 typedef class HashMap {
 16     private:
 17         static const int M = 46666; 
 18     public:
 19         int ce;
 20         int h[M], key[M], val[M], next[M];
 21         
 22         HashMap() {    }
 23         
 24         void insert(int k, int v) {
 25             int ha = k % M;
 26             for (int i = h[ha]; ~i; i = next[i])
 27                 if (key[i] == k) {
 28                     val[i] = v;
 29                     return;
 30                 }
 31             ++ce, key[ce] = k, val[ce] = v, next[ce] = h[ha], h[ha] = ce;
 32         }
 33         
 34         int operator [] (int k) {
 35             int ha = k % M;
 36             for (int i = h[ha]; ~i; i = next[i])
 37                 if (key[i] == k)
 38                     return val[i];
 39             return -1;
 40         }
 41         
 42         void clear() {
 43             ce = -1;
 44             memset(h, -1, sizeof(h));
 45         }
 46 }HashMap; 
 47 
 48 void exgcd(int a, int b, int& d, int& x, int& y) {
 49     if (!b)
 50         d = a, x = 1, y = 0;
 51     else {
 52         exgcd(b, a % b, d, y, x);
 53         y -= (a / b) * x;
 54     }
 55 }
 56 
 57 int qpow(int a, int pos, int p) {
 58     int pa = a, rt = 1;
 59     for ( ; pos; pos >>= 1, pa = pa * 1ll * pa % p)
 60         if (pos & 1)
 61             rt = rt * 1ll * pa % p;
 62     return rt;
 63 }
 64 
 65 int inv(int a, int n) {
 66     int d, x, y;
 67     exgcd(a, n, d, x, y);
 68     return (x < 0) ? (x + n) : (x);
 69 }
 70 
 71 int p, k, a;
 72 int g;
 73 
 74 inline void init() {
 75     scanf("%d%d%d", &p, &k, &a);
 76 }
 77 
 78 HashMap mp;
 79 int ind(int a, int b, int p) {
 80     mp.clear();
 81     int cs = sqrt(p - 0.5), ac = qpow(a, cs, p), iac = b * 1ll * inv(ac, p) % p, pw = 1;
 82     for (int i = cs - 1; ~i; i--)
 83         iac = iac * 1ll * a % p, mp.insert(iac, i);
 84     for (int i = 0; i < p; i += cs, pw = pw * 1ll * ac % p)
 85         if (~mp[pw])
 86             return mp[pw] + i;
 87     return -1;
 88 }
 89 
 90 int top = 0;
 91 int fac[50];
 92 void getfactors(int x) {
 93     for (int i = 2; i * i <= x; i++) {
 94         if (!(x % i)) {
 95             fac[++top] = i;
 96             while (!(x % i))    x /= i; 
 97         }
 98     }
 99     if (x != 1)    fac[++top] = x;
100 }
101 
102 boolean isroot(int x) {
103     int pos = p - 1;
104     for (int i = 1; i <= top; i++)
105         if (qpow(x, pos / fac[i], p) == 1)
106             return false;
107     return true;
108 }
109 
110 inline void solve() {
111     if (p == 1 || !a) {
112         printf("1\n0");
113         return;
114     }
115     if (p == 2)
116         g = 1;
117     else {
118         getfactors(p - 1);
119         for (g = 2; !isroot(g); g++);
120     }
121 
122     int inda = ind(g, a, p), d, x, y, cir;
123     exgcd(k, p - 1, d, x, y);
124     if (inda % d) {
125         puts("0");
126         return;
127     }
128     cir = (p - 1) / d;
129     x = x * 1ll * (inda / d) % cir;
130     (x <= 0) ? (x += cir) : (0);
131     vector<int> res;
132     for (; x < p; x += cir)
133         res.push_back(qpow(g, x, p));
134     sort(res.begin(), res.end());
135     printf("%d\n", (signed) res.size());
136     for (int i = 0; i < (signed) res.size(); i++)
137         printf("%d\n", res[i]);
138 }
139 
140 int main() {
141     init();
142     solve();
143     return 0;
144 }
posted @ 2018-03-01 11:08  阿波罗2003  阅读(...)  评论(... 编辑 收藏