题目链接: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.
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.
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.
Prime | Corresponding Mersenne Number |
---|---|
2 | 4–1 = 3 -- prime |
3 | 8–1 = 7 -- prime |
5 | 32–1 = 31 -- prime |
7 | 128–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;
}
}