【BZOJ4522】【CQOI2016】密钥破解

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

【题目链接】

【思路要点】

  • N 分解为 p q ,计算得到 r = ( p 1 ) ( q 1 )
  • e x g c d 计算一个合法的 d ,使得 e d 1 ( m o d     r ) 即可。
  • 分解质因数需要 P o l l a r d s   r h o 算法
  • 时间复杂度 O ( L o g N + N 1 4 + N 1 4 α ( N ) β + β α ( N ) )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 100005;
const int steps = 512;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
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 e, n, c, r;
ll times(ll a, ll b) {
  ll tmp = (ld) a * b / n;
  return ((a * b - tmp * n) % n + n) % n;
}
ll f(ll x, ll add) {
  x = times(x, x) + add;
  if (x >= n) x -= n;
  return x;
}
ll mns(ll x, ll y) {
  if (x >= y) return x - y;
  else return y - x;
}
ll gcd(ll x, ll y) {
  if (y == 0) return x;
  else return gcd(y, x % y);
}
ll power(ll x, ll y) {
  if (y == 0) return 1;
  ll tmp = power(x, y / 2);
  if (y % 2 == 0) return times(tmp, tmp);
  else return times(times(tmp, tmp), x);
}
ll brent(ll add) {
  if (n % 2 == 0) return 2;
  ll x = 2, y = 2;
  while (true) {
      ll tmpx = x, tmpy = y, d = 1;
      for (int i = 1; i <= 512; i++) {
          x = f(x, add);
          y = f(f(y, add), add);
          d = times(d, gcd(n, mns(x, y)));
      }
      d = gcd(n, d);
      if (d == 1) continue;
      if (d != n) return d;
      x = tmpx, y = tmpy;
      for (int i = 1; i <= 512; i++) {
          x = f(x, add);
          y = f(f(y, add), add);
          d = gcd(n, mns(x, y));
          if (d != 1) return d % n;
      }
  }
}
void exgcd(ll a, ll b, ll &x, ll &y) {
  if (b == 0) {
      x = 1;
      y = 0;
      return;
  }
  exgcd(b, a % b, y, x);
  y += a / b * x;
  x = -x, y = -y;
}
int main() {
  read(e), read(n), read(c);
  ll p = 0, q = 0;
  for (ll i = 1; !(p = brent(i)); i++);
  q = n / p , r = (p - 1) * (q - 1);
  ll x = 0, y = 0;
  exgcd(e, r, x, y);
  x = (x % r + r) % r;
  printf("%lld %lld\n", x, power(c, x));
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/82348380