zoukankan      html  css  js  c++  java
  • 素数专题

    素数是一个经常的涉及到得内容,所以有必要整理出有关解决素数相关问题的算法

    学习资料:Eratosthenes筛法和欧拉筛法对比  一般筛法求素数+快速线性筛法求素数  数学技巧之素数筛选

         素数与素性测试 〖数学算法〗素性测试  请看Miller-Rabin算法!  Miller-Rabin素数测试  Pollard-rho大整数分解

    1. 素数筛法

      代码1(埃氏筛法):

    /*
        埃氏筛法:返回n以内素数的个数, 复杂度O (nloglogn)
    */
    int seive(int n)    {        //Eratosthenes (埃氏筛法)
        int p = 0;
        memset (is_prime, true, sizeof (is_prime));
        is_prime[0] = is_prime[1] = false;
        for (int i=2; i<=n; ++i)    {
            if (is_prime[i])    {
                prime[++p] = i;
                for (int j=2*i; j<=n; j+=i)    is_prime[j] = false;
            }
        }
        return p;
    }
    

      代码2(欧拉筛法):

    /*
        欧拉筛法:返回n以内素数的个数, 复杂度O (n)
    */
    int seive(int n)    {        //Euler (欧拉筛法)
        int p = 0;
        memset (is_prime, true, sizeof (is_prime));
        is_prime[0] = is_prime[1] = false;
        for (int i=2; i<=n; ++i)    {
            if (is_prime[i])    prime[++p] = i;
            for (int j=1; j<=p && i*prime[j]<=n; ++j)    {
                is_prime[i*prime[j]] = false;
                if (i % prime[j] == 0)    break;
            }
        }
        return p;
    }

    附上比较两种筛法的测试结果(新标签查看原图)

    2. 素性测试

      代码1:

    /*
        素性测试,输入正数,复杂度O (sqrt(n))
    */
    bool is_prime(int n)    {
        for (int i=2; i*i<=n; ++i)  {
            if (n % i == 0)    return false;
        }
        return n != 1;    //1例外
    }
    

      代码2:

    /*
        素性测试,在小范围(1e5)内判素数个数以及单个数判素数有奇效,不适用于大范围判素数
    */
    bool is_prime(int x)    {
        if (x == 2 || x == 3)   return true;
        if (x % 6 != 1 && x % 6 != 5)   return false;
        for (int i=5; i*i<=x; i+=6) {
            if (x % i == 0 || x % (i + 2) == 0) return false;
        }
        return true;
    }
    

      代码3(Miller_Rabin 随机算法):

    /*
    	素性测试,Miller_Rabin 随机算法
    	可以判断< 2^63的数
    	素数:true,合数:false
    */
    const int S = 20;									//随机算法判定次数,S越大,判错概率越小
    
    //非递归写法,递归写法可能会爆栈
    ll GCD(ll a, ll b)	{
    	if (a == 0)	return 1;
    	if (a < 0)	a = -a;
    	while (b)	{
    		ll c = a % b;
    		a = b; b = c;
    	}
    	return a;
    }
    
    //计算 (a * b) % p,a,b是long long数,直接相乘可能会溢出
    ll multi_mod(ll a, ll b, ll p)	{
    	ll ret = 0;
    	a %= p;	b %= p;
    	while (b)	{
    		if (b & 1)	{
    			ret += a;
    			if (ret >= p)	ret -= p;
    		}
    		a <<= 1;
    		if (a >= p)	a -= p;
    		b >>= 1;
    	}
    	return ret;
    }
    
    //计算 a ^ x % p
    ll pow_mod(ll a, ll x, ll p)	{
    	ll ret = 1;
    	a %= p;
    	while (x)	{
    		if (x & 1)	ret = multi_mod (ret, a, p);
    		a = multi_mod (a, a, p);
    		x >>= 1;
    	}
    	return ret;
    }
    
    /*
    	以a为基,n-1=x*2^t,a^(n-1) = 1(mod n)  验证n是不是合数
    	一定是合数返回true, 不一定返回false
    */
    bool check(ll a, ll n, ll x, int t)	{
    	ll ret = pow_mod (a, x, n);
    	ll last = ret;
    	for (int i=1; i<=t; ++i)	{
    		ret = multi_mod (ret, ret, n);
    		if (ret == 1 && last != 1 && last != n - 1)	return true;	//合数
    		last = ret;
    	}
    	if (ret != 1)	return true;
    	return false;
    }
    
    bool Miller_Rabin(ll n)	{
    	if (n == 2)	return true;
    	if (n < 2 || ! (n & 1))	return false;			//偶数或1
    	ll x = n - 1;	int t = 0;
    	while (! (x & 1))	{
    		x >>= 1;	t++;
    	}
    	for (int i=1; i<=S; ++i)	{
    		ll a = rand () % (n - 1) + 1;				//需要cstdlib头文件
    		if (check (a, n, x, t))	return false;		//合数
    	}
    	return true;
    }
    

      

     3. 整数分解

      代码1:

    /*
        整数分解,试除法进行质因子分解,复杂度O(sqrt(n))
    */
    map<int, int> factorize(int n)   {
        map<int, int> res;
        for (int i=2; i*i<=n; ++i)  {
            while (n % i == 0)    {
                ++res[i];    n /= i;
            }
        }
        if (n != 1)    res[n] = 1;
        return res;
    }
    

      代码2:

    /*
        整数分解,先打个素数表优化试除法
    */
    vector<int> factorize(int n)  {
        int p = seive (100000);
        vector<int> ret;
        for (int i=1; i<=p && prime[i]<=n/prime[i]; ++i)    {
            while (n % prime[i] == 0)  {
                n /= prime[i];
                ret.push_back (prime[i]);
            }
        }
        if (n != 1) ret.push_back (n);
        return ret;
    }
    

      代码3(Pollard_rho 随机算法):

    /*
    	大整数分解,Pollard_rho 随机算法
    	factorize ()保存质因数在vector
    */
    ll Pollard_rho(ll x, ll c)	{
    	ll i = 1, k = 2;
    	ll a = rand () % x;
    	ll b = a;
    	while (1)	{
    		i++;
    		a = (multi_mod (a, a, x) + c) % x;
    		ll d = GCD (b - a, x);
    		if (d != 1 && d != x)	return d;
    		if (b == a)	return x;
    		if (i == k)	b = a, k += k;
    	}
    }
    
    void factorize(ll n, vector<ll> &ret)	{			//ret保存质因数,无序
    	if (Miller_Rabin (n))	{						//素数
    		ret.push_back (n);	return ;
    	}
    	ll p = n;
    	while (p >= n)	p = Pollard_rho (p, rand () % (n - 1) + 1);
    	factorize (p, ret);
    	factorize (n / p, ret);
    }
    
    
    int main(void)    {
    	srand (time (NULL));							//需添加ctime头文件
    	int T;	scanf ("%d", &T);
    	while (T--)	{
    		ll n;	scanf ("%I64d", &n);
    		if (Miller_Rabin (n))	puts ("Prime");
    		else	{
    			if (n <= 1)	{							//1的情况特判,否则RE
    				puts ("-1");	continue;
    			}
    			vector<ll> ans;
    			factorize (n, ans);
    			sort (ans.begin (), ans.end ());
    			for (int i=0; i<ans.size (); ++i)	{
    				printf ("%I64d%c", ans[i], (i == ans.size ()-1) ? '
    ' : ' ');
    			}
    		}
    	}
    	
        return 0;
    }

      

    其他:

      代码:

    /*
        约数枚举,复杂度O (sqrt(n))
    */
    vector<int> divisor(int n)  {
        vector<int> ret;
        for (int i=1; i*i<=n; ++i)  {
            if (n % i == 0) {
                ret.push_back (i);
                if (n / i != i)    ret.push_back (n / i);
            }
        }
        return res;
    }
    编译人生,运行世界!
  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4736142.html
Copyright © 2011-2022 走看看