码迷,mamicode.com
首页 > 其他好文 > 详细

幂方程(模意义下)

时间:2019-09-11 23:52:40      阅读:125      评论:0      收藏:0      [点我收藏+]

标签:mit   end   最小   put   class   ber   分析   phi   模型   

问题

求解 $$x^a\equiv b(mod \ p)$$

其中 $p$ 为质数

分析

由于 $p$ 为质数,肯定存在原根 $g$。

由原根的定义知 $x$ 可表示成 $x=g^c$,问题转化为 $(g^c)^a \equiv b(mod \ p)$,得到

$$(g^a)^c \equiv b(mod \ p)$$

于是就转换成我们熟悉的BSGS模型了,可以在 $O(\sqrt p logp)$ 解出 $c$。

这样得到原方程的一个特解 $x_0 \equiv g^c(mod \ p)$。显然,这个解不一定是最小解。

如何求出最小解呢?

由于存在取模操作,需要求出所有解。

如何求出所有解呢?

已知 $x0=g^c$ 为其中一个解,设另外一个解 $g^{c+ delt}$ ,有

$$(g^{c+delt})^a \equiv b(mod \ p)$$

推出 $g^{delt\cdot a} \equiv 1(mod \ p)$,进一步有 $delt \cdot a \mid \varphi (p)$,所以 $delt$ 最小为 $delt = \frac{\varphi (p)}{gcd(a, \varphi (p))}$.

易知,$g^{c+k * delt}$ 都是方程的解。 

 

//下面贴出求所有解的模板,注意可能爆int!!

int gcd(int a, int b) { return a ? gcd(b % a, a) : b; }
int powmod(int a, int b, int p) {
  int res = 1;
  while (b > 0) {
    if (b & 1) res = res * a % p;
    a = a * a % p, b >>= 1;
  }
  return res;
}
// Finds the primitive root modulo p
int generator(int p) {
  vector<int> fact;
  int phi = p - 1, n = phi;
  for (int i = 2; i * i <= n; ++i) {
    if (n % i == 0) {
      fact.push_back(i);
      while (n % i == 0) n /= i;
    }
  }
  if (n > 1) fact.push_back(n);
  for (int res = 2; res <= p; ++res) {
    bool ok = true;
    for (int factor : fact) {
      if (powmod(res, phi / factor, p) == 1) {
        ok = false;
        break;
      }
    }
    if (ok) return res;
  }
  return -1;
}
// This program finds all numbers x such that x^k=a (mod n)
int main() {
  int n, k, a;
  scanf("%d %d %d", &n, &k, &a);
  if (a == 0) return puts("1\n0"), 0;
  int g = generator(n);
  // Baby-step giant-step discrete logarithm algorithm
  int sq = (int)sqrt(n + .0) + 1;
  vector<pair<int, int>> dec(sq);
  for (int i = 1; i <= sq; ++i)
    dec[i - 1] = {powmod(g, i * sq * k % (n - 1), n), i};
  sort(dec.begin(), dec.end());
  int any_ans = -1;
  for (int i = 0; i < sq; ++i) {
    int my = powmod(g, i * k % (n - 1), n) * a % n;
    auto it = lower_bound(dec.begin(), dec.end(), make_pair(my, 0));
    if (it != dec.end() && it->first == my) {
      any_ans = it->second * sq - i;
      break;
    }
  }
  if (any_ans == -1) return puts("0"), 0;
  // Print all possible answers
  int delta = (n - 1) / gcd(k, n - 1);
  vector<int> ans;
  for (int cur = any_ans % delta; cur < n - 1; cur += delta)
    ans.push_back(powmod(g, cur, n));
  sort(ans.begin(), ans.end());
  printf("%d\n", ans.size());
  for (int answer : ans) printf("%d ", answer);
}

 

 

参考链接:https://oi-wiki.org/math/bsgs/

幂方程(模意义下)

标签:mit   end   最小   put   class   ber   分析   phi   模型   

原文地址:https://www.cnblogs.com/lfri/p/11509443.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!