HDu 2138 How many prime numbers 高效Miller素数測试

题目就是给出一组数。让我们測试当中有多少个是素数。

求素数有測试sqrt(n)个数的方法。有筛子方法,只是对于本题这种题目来说就都不是高效的。

本题使用Miller Rabin素数測试法。效率奇高。对于不是极其大的整数測试都差点儿是常数时间。令人神往的算法啊。

网上有个程序,好像是什么吉林的模板程序,只是我一直没看懂他是什么思路写的,是个AC的程序,只是却是错误的,呵呵,由于程序一直把9当做素数。

于是上网查找了当中原理,自己写了个程序,效率和他的几乎相同一样。通过时间基本无区别,只是我的思路是依照wiki上的写的。

wiki介绍样例:

Example[edit]

Suppose we wish to determine if n = 221 is prime. We write n ? 1 = 220 as 22·55, so that we have s = 2 and d = 55. We randomly select
a number a such that a < n, say a = 174. We proceed to compute:

  • a20·d mod n = 17455 mod 221 = 47 ≠ 1, n ? 1
  • a21·d mod n = 174110 mod 221 = 220 = n ? 1.

Since 220 ≡ ?1 mod n, either 221 is prime, or 174 is a strong liar for 221. We try another random a, this time choosing a = 137:

  • a20·d mod n = 13755 mod 221 = 188 ≠ 1, n ? 1
  • a21·d mod n = 137110 mod 221 = 205 ≠ n ? 1.

Hence 137 is a witness for the compositeness of 221, and 174 was in fact a strong liar. Note that this tells us nothing about the factors of 221 (which are 13 and 17). However, the example with 341 in the next section shows how these calculations can sometimes
produce a factor of n.

出处:http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test

參照上面样例就能够敲代码了。挺难写的一个程序,运用好数论知识和位运算才干写出高效的程序:

代码乃属原创,转载请注明作者:

作者 靖心 http://blog.csdn.net/kenden23/article/details/30478591

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cmath>
__int64 s, d;

void preCalsd(__int64 N)
{
	s = 0;
	N--;
	while ((N & 1) == 0)
	{
		s++;
		N >>= 1LL;
	}
	d = N;
}

__int64 fastPowMod(__int64 base, __int64 num, __int64 mod)
{
	__int64 ans = 1LL;
	while (num)
	{
		if (num & 1) ans = ans * base % mod;
		base = base * base % mod;
		num >>= 1LL;
	}
	return ans % mod;
}

bool witness(__int64 a, __int64 N)
{
	__int64 num = d, m = -1;
	for (int i = 0; i < s; i++)
	{
		num = d * (1LL << i);
		m = fastPowMod(a, num, N);
		if (m == 1 || m == N-1) return false;
	}
	return true;
}

bool miller_rabin(__int64 N)
{
	if(N == 2)	return true;
	if(N == 1 || ((N&1) == 0))	return false;

	preCalsd(N);
	for(int i = 0; i < 3; i++) //i < 50
	{
		__int64 a = 2 + rand() % (N-2);
		if(witness(a, N)) return false;
	}
	return true;
}

int main()
{
	srand(unsigned(time(NULL)));
	int n,cnt;
	__int64 a;
	while(scanf("%d", &n)!=EOF)
	{
		cnt = 0;
		while(n--)
		{
			scanf("%I64d", &a);
			if(miller_rabin(a))
			{
				cnt++;
				//printf("%d ", a);
			}
		}
		printf("%d\n",cnt);
	}
	return 0;
}
时间: 2024-10-10 01:53:36

HDu 2138 How many prime numbers 高效Miller素数測试的相关文章

HDu 2138 How many prime numbers 高效Miller素数测试

题目就是给出一组数,让我们测试其中有多少个是素数. 求素数有测试sqrt(n)个数的方法,有筛子方法,不过对于本题这样的题目来说就都不是高效的. 本题使用Miller Rabin素数测试法,效率奇高,对于不是极其大的整数测试都几乎是常数时间.令人神往的算法啊. 网上有个程序,好像是什么吉林的模板程序,不过我一直没看懂他是什么思路写的,是个AC的程序,不过却是错误的,呵呵,因为程序一直把9当做素数. 于是上网查找了其中原理,自己写了个程序,效率和他的差不多一样,通过时间基本无差别,不过我的思路是按

HDU 2138 How many prime numbers (判素数,米勒拉宾算法)

题意:给定一个数,判断是不是素数. 析:由于数太多,并且太大了,所以以前的方法都不适合,要用米勒拉宾算法. 代码如下: #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring> #include <map> #include <cctype> u

HDU 2138 How many prime numbers(Miller_Rabin法判断素数 【*模板】 用到了快速幂算法 )

How many prime numbers Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12955    Accepted Submission(s): 4490 Problem Description Give you a lot of positive integers, just to find out how many pr

HDOJ(HDU) 2138 How many prime numbers(素数-快速筛选没用上、)

Problem Description Give you a lot of positive integers, just to find out how many prime numbers there are. Input There are a lot of cases. In each case, there is an integer N representing the number of integers to find. Each integer won't exceed 32-

HDU 2138 How many prime numbers

就是找素数. 非常水的题.模糊搜索一道题搜到的. 可是却 TLE 2次.把全部的 long long 改成 int ,%lld 改成 %d 就奇妙的过了. 简直不可思议. #include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<stack> #include&

POJ2429_GCD &amp;amp; LCM Inverse【Miller Rabin素数測试】【Pollar Rho整数分解】

GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a and b.

POJ1811_Prime Test【Miller Rabin素数測试】【Pollar Rho整数分解】

Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time Limit: 4000MS Description Given a big integer number, you are required to find out whether it's a prime number. Input The first line contains the num

How many prime numbers(求素数个数)

How many prime numbers Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 14684    Accepted Submission(s): 5091 Problem Description Give you a lot of positive integers, just to find out how many p

【HDU】2138 How many prime numbers

http://acm.hdu.edu.cn/showproblem.php?pid=2138 题意:给n个数判断有几个素数.(每个数<=2^32) #include <cstdio> using namespace std; typedef long long ll; ll ipow(ll a, ll b, ll m) { ll x=1; for(; b; b>>=1, (a*=a)%=m) if(b&1) (x*=a)%=m; return x; } ll rand