• HDU-2138-How many prime numbers(Miller-Rabin新解法)


    题目传送门

    sol1:普通判到sqrt(n)的素数判定,不多说了。

    • 素数判定
      #include "bits/stdc++.h"
      using namespace std;
      bool is_prime(int n) {
          for (int i = 2; 1LL * i * i <= n; i++)
          {
              if (n % i == 0) return false;
          }
          return true;
      }
      int main() {
          int n, m;
          while (~scanf("%d", &n)) {
              int cnt = 0; 
              for (int i = 1; i <= n; i++) {
                  scanf("%d", &m);
                  if (is_prime(m)) cnt++;
              }
              printf("%d
      ", cnt);
          }
          return 0;
      }

      复杂度sqrt(m),判断n次就是n * sqrt(m);

    sol2:新get到的技巧Miller-Rabin素数测试,结合了费马小定理和二次探测定理,可以更高效的判断素数,存在误判可能,不过误判可能非常小,可以忽略不计;

    • Miller-Rabin素数测试
      #include "bits/stdc++.h"
      using namespace std;
      int quick_pow(int n, int k, int p) {
          int ans = 1;
          while (k) {
              if (k & 1) ans = 1LL * ans * n % p;
              n = 1LL * n * n % p;
              k >>= 1;
          }
          return ans;
      }
      bool is_prime(int n) {
      //    if (n < 2) return false;
          int s = 0, t = n - 1;
          while (!(t & 1)) s++, t >>= 1;
          for (int i = 1; i <= 5; i++) {
              int a = rand() % (n - 1) + 1;
              int k = quick_pow(a, t, n);
              for (int j = 1; j <= s; j++) {
                  int x = 1LL * k * k % n;
                  if (x == 1 && k != 1 && k != n - 1) return false;
                  k = x;
              }
              if (k != 1) return false;
          }
          return true;
      }
      int main() {
          int n, m;
          srand(time(NULL));
          while (~scanf("%d", &n)) {
              int cnt = 0;
              for (int i = 1; i <= n; i++) {
                  scanf("%d", &m);
                  if (is_prime(m)) cnt++;
              }
              printf("%d
      ", cnt);
          }
          return 0;
      }

      复杂度logm,判断n次就是n * log(m);

    附加一个用于 LL 范围素数测试的模板:s

    • Miller-Rabin素数测试 LL 范围模板
      typedef long long LL;
      LL quick_mul(LL n, LL k, LL p) {
          LL ans = 0;
          while (k) {
              if (k & 1) ans = (ans + n) % p;
              n = (n + n) % p;
              k >>= 1;
          }
          return ans;
      }
      LL quick_pow(LL n, LL k, LL p) {
          LL ans = 1;
          while (k) {
              if (k & 1) ans = quick_mul(ans, n, p);
              n = quick_mul(n, n, p);
              k >>= 1;
          }
          return ans;
      }
      bool is_prime(LL n) {
          if (n < 2) return false;
          LL s = 0, t = n - 1;
          while (!(t & 1)) s++, t >>= 1;
          for (int i = 1; i <= 5; i++) {
              LL a = rand() % (n - 1) + 1;
              LL k = quick_pow(a, t, n);
              for (int j = 1; j <= s; j++) {
                  LL x = quick_mul(k, k, n);
                  if (x == 1 && k != 1 && k != n - 1) return false;
                  k = x;
              }
              if (k != 1) return false;
          }
          return true;
      }

      大致差不多,为了防止爆 LL 加了一个快速积用于乘, 所以复杂度变成了log(m) * log(m)

  • 相关阅读:
    oracle查找前几条记录
    linux主要目录
    openstack搭建3、部署xinetd服务
    openstack搭建1、前期准备
    openstack搭建2、部署Mariadbgalera
    Java 基础(类的加载与ClassLoader的理解)
    K8S 查看资源使用情况
    Java 基础 (Java 反射机制)
    Java 基础 (网络编程 TCP 例子)
    Java 基础 (网络编程 UDP 例子, URL)
  • 原文地址:https://www.cnblogs.com/Angel-Demon/p/11589211.html
Copyright © 2020-2023  润新知