【BZOJ3667】Rabin-Miller算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/82347044

【题目链接】

【思路要点】

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 100005;
const int p[9] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
typedef long long ll;
typedef long double ld;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
ll times(ll a, ll b, ll P) {
  ll tmp = (ld) a * b / P;
  return ((a * b - tmp * P) % P + P) % P;
}
ll mns(ll a, ll b) {
  if (a >= b) return a - b;
  else return b - a;
}
ll gcd(ll a, ll b) {
  if (b == 0) return a;
  else return gcd(b, a % b);
}
ll power(ll a, ll b, ll P) {
  if (b == 0) return 1;
  ll tmp = power(a, b / 2, P);
  if (b % 2 == 0) return times(tmp, tmp, P);
  else return times(a, times(tmp, tmp, P), P);
}
bool prime(ll n) {
  for (int i = 0; i <= 8; i++) {
      if (p[i] == n) return true;
      else if (p[i] > n) return false;
      ll tmp = power(p[i], n - 1, n), tnp = n - 1;
      if (tmp != 1) return false;
      while (tmp == 1 && tnp % 2 == 0) {
          tnp /= 2;
          tmp = power(p[i], tnp, n);
          if (tmp == n - 1) break;
          if (tmp != 1) return false;
      }
  }
  return true;
}
ll brent(ll n, int steps, int add) {
  if (n % 2 == 0) return 2;
  ll x = 2, y = 2, d = 1;
  while (true) {
      ll tmpx = x, tmpy = y;
      for (int i = 1; i <= steps; i++) {
          x = times(x, x, n) + add;
          if (x >= n) x -= n;
          y = times(y, y, n) + add;
          if (y >= n) y -= n;
          y = times(y, y, n) + add;
          if (y >= n) y -= n;
          d = times(d, mns(x, y), n);
      }
      d = gcd(n, d);
      if (d == 1) continue;
      if (d != n) return d;
      x = tmpx, y = tmpy;
      for (int i = 1; i <= steps; i++) {
          x = times(x, x, n) + add;
          if (x >= n) x -= n;
          y = times(y, y, n) + add;
          if (y >= n) y -= n;
          y = times(y, y, n) + add;
          if (y >= n) y -= n;
          d = gcd(n, mns(x, y));
          if (d != 1) return d % n;
      }
      return 0;
  }
}
ll work(ll n) {
  if (prime(n)) return n; ll tmp = 0;
  int steps = pow(n, 0.1), add = 1;
  while (tmp == 0) tmp = brent(n, steps, add++);
  return max(work(tmp), work(n / tmp));
}
int main() {
  int T; read(T);
  while (T--) {
      ll n; read(n);
      ll tmp = work(n);
      if (tmp == n) printf("Prime\n");
      else printf("%lld\n", tmp);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/82347044
今日推荐