(部分转载)POJ2191Mersenne Composite Numbers梅森素数

题目链接:POJ2191Mersenne Composite Numbers梅森素数

Mersenne Composite Numbers
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2361 Accepted: 1102

Description

One of the world-wide cooperative computing tasks is the "Grand Internet Mersenne Prime Search" -- GIMPS -- striving to find ever-larger prime numbers by examining a particular category of such numbers. 
A Mersenne number is defined as a number of the form (2 p–1), where p is a prime number -- a number divisible only by one and itself. (A number that can be divided by numbers other than itself and one are called "composite" numbers, and each of these can be uniquely represented by the prime numbers that can be multiplied together to generate the composite number — referred to as its prime factors.) 
Initially it looks as though the Mersenne numbers are all primes. 
PrimeCorresponding Mersenne Number
24–1 = 3 -- prime
38–1 = 7 -- prime
532–1 = 31 -- prime
7128–1 = 127 -- prime

If, however, we are having a "Grand Internet" search, that must not be the case. 
Where k is an input parameter, compute all the Mersenne composite numbers less than 2 k -- where k <= 63 (that is, it will fit in a 64-bit signed integer on the computer). In Java, the "long" data type is a signed 64 bit integer. Under gcc and g++ (C and C++ in the programming contest environment), the "long long" data type is a signed 64 bit integer. 

Input

Input contains a single number, without leading or trailing blanks, giving the value of k. As promised, k <= 63.

Output

One line per Mersenne composite number giving first the prime factors (in increasing order) separate by asterisks, an equal sign, the Mersenne number itself, an equal sign, and then the explicit statement of the Mersenne number, as shown in the sample output. Use exactly this format. Note that all separating white space fields consist of one blank.

Sample Input

31

Sample Output

23 * 89 = 2047 = ( 2 ^ 11 ) - 1
47 * 178481 = 8388607 = ( 2 ^ 23 ) - 1
233 * 1103 * 2089 = 536870911 = ( 2 ^ 29 ) - 1

Source

题目的意思是输入一个数K,且K<=63,然后判断所有质数i<=k,2^i-1是否是质数,不是的话就要将它分解质因数输出来。例如输入31的时候,11、23、29不满足条件,他们的2^i-1不是质数,于是将这个合数分解开来,以题目所示的格式输出。

题目有两种解法,第一种是打表,第二种是miller_rabin判,pollard-pho分解,类似于枚举。

首先第一种解法,因为K是<=63的,所以先找出63以内所有2^i-1不是质数的数来,求出其分解因式,打好表。到时候直接根据输入的K值输出即可。代码如下:

#include<iostream>  
#include<cstdio>  
#include<cstring>  
using namespace std;  
int main(){  
      
 string s1="23 * 89 = 2047 = ( 2 ^ 11 ) - 1";  
 string s2="47 * 178481 = 8388607 = ( 2 ^ 23 ) - 1";  
 string s3="233 * 1103 * 2089 = 536870911 = ( 2 ^ 29 ) - 1";  
 string s4="223 * 616318177 = 137438953471 = ( 2 ^ 37 ) - 1";  
 string s5="13367 * 164511353 = 2199023255551 = ( 2 ^ 41 ) - 1";  
 string s6="431 * 9719 * 2099863 = 8796093022207 = ( 2 ^ 43 ) - 1";  
 string s7="2351 * 4513 * 13264529 = 140737488355327 = ( 2 ^ 47 ) - 1";  
 string s8="6361 * 69431 * 20394401 = 9007199254740991 = ( 2 ^ 53 ) - 1";  
 string s9="179951 * 3203431780337 = 576460752303423487 = ( 2 ^ 59 ) - 1";  
    int k;  
    while(cin>>k){  
        if(k>=11&&k<=22) cout<<s1<<endl;  
        if(k>=23&&k<=28) cout<<s1<<endl<<s2<<endl;  
        if(k>=29&&k<=36) cout<<s1<<endl<<s2<<endl<<s3<<endl;  
        if(k>=37&&k<=40) cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl;  
        if(k>=41&&k<=42) cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl<<s5<<endl;  
        if(k>=43&&k<=46) cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl<<s5<<endl<<s6<<endl;  
        if(k>=47&&k<=52) cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl<<s5<<endl<<s6<<endl<<s7<<endl;  
        if(k>=53&&k<=58) cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl<<s5<<endl<<s6<<endl<<s7<<endl<<s8<<endl;  
        if(k>=59&&k<=63) cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl<<s5<<endl<<s6<<endl<<s7<<endl<<s8<<endl<<s9<<endl;  
    }  
} 

第二种解法:(是真的难。。。。。吃我大鼻孔 微笑哦不,卡姿兰大眼睛)

首先,安利一下几个知识点。

1、random_shuffle

STL中的函数random_shuffle()用来对一个元素序列进行重新排序(随机的),函数原型如下:

template<class RandomAccessIterator>  
   void random_shuffle(  
      RandomAccessIterator _First, //指向序列首元素的迭代器  
      RandomAccessIterator _Last  //指向序列最后一个元素的下一个位置的迭代器  
   );

2、 miller_rabin素数测试法

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
using namespace std;

const int times = 20;
int number = 0;

map<long long, int>m;
long long Random( long long n )         //生成[ 0 , n ]的随机数
{
    return ((double)rand( ) / RAND_MAX*n + 0.5);
}
long long q_mul( long long a, long long b, long long mod ) //快速计算 (a*b) % mod
{
    long long ans = 0;
    while(b)
    {
        if(b & 1)
        {
            b--;
            ans =(ans+ a)%mod;
        }
        b /= 2;
        a = (a + a) % mod;
    }
    return ans;
}
long long q_pow( long long a, long long b, long long mod ) //快速计算 (a^b) % mod
{
    long long ans = 1;
    while(b)
    {
        if(b & 1)
        {
            ans = q_mul( ans, a, mod );
        }
        b /= 2;
        a = q_mul( a, a, mod );
    }
    return ans;
}
bool witness( long long a, long long n )//miller_rabin算法的精华
{//用检验算子a来检验n是不是素数
    long long tem = n - 1;
    int j = 0;
    while(tem % 2 == 0)
    {
        tem /= 2;
        j++;
    }
    //将n-1拆分为a^r * s

    long long x = q_pow( a, tem, n ); //得到a^r mod n
    if(x == 1 || x == n - 1) return true;   //余数为1则为素数
    while(j--) //否则试验条件2看是否有满足的 j
    {
        x = q_mul( x, x, n );
        if(x == n - 1) return true;
    }
    return false;
}
bool miller_rabin( long long n )  //检验n是否是素数
{

    if(n == 2)
        return true;
    if(n < 2 || n % 2 == 0)
        return false;               //如果是2则是素数,如果<2或者是>2的偶数则不是素数

    for(int i = 1; i <= times; i++)  //做times次随机检验
    {
        long long a = Random( n - 2 ) + 1; //得到随机检验算子 a
        if(!witness( a, n ))                        //用a检验n是否是素数
            return false;
    }
    return true;
}
int main()
{
    long long tar;
    while(cin >> tar)
    {
        if(miller_rabin( tar )) //检验tar是不是素数
            cout << "Yes, Prime!" << endl;
        else
            cout << "No, not prime.." << endl;
    }
    return 0;
}


3、Pollard整数质因子分解

int pollard_rho(int n, int c)///c为自己设定的某值  
{  
    int x, y, d, i = 1, k = 2;  
    x = rand() % (n - 1) + 1;  
    y = x;  
    while (true) {  
        ++i;  
        x = (modular_multi(x, x, n) + c) % n;  
        d = gcd(y - x, n);  
        if (1 < d && d < n)  
            return d;  
        if (x == y)  
            return n;  
        if (i == k)  
            y = x, k <<= 1;  
    }  
}  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值