題目
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
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 (2p–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 2k -- 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 is from file a. in. It 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
題目大意
找出指數(shù)為63或以下的不是素數(shù)的梅森數(shù)。
思路
- 有限小個數(shù)答案的問題句旱,效率最高的是枚舉所有可能的答案倦踢,也就是所謂的直接打表九孩。(然而有作弊的嫌疑)
- 建立好素數(shù)表兽肤,然后從中篩選。(然而那么大量數(shù)據(jù)的表庸娱,還沒建好都TLE了)
- 簡單粗暴地對每個數(shù)進行質因數(shù)分解赃额。(然而一定會TLE)
- 只針對符合答案的情況進行計算。(其實這樣子和打表沒有什么區(qū)別)
代碼
直接打表版
網上說算到59就夠了卓舵,是因為$2^{61}-1$是一個梅森素數(shù)南用,這里不用輸出。
// Copyright (c) 2015 HuangJunjie@SYSU(SNO:13331087). All Rights Reserved.
// sicily 1009: http://soj.sysu.edu.cn/1009
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int main() {
int max;
int answer[9] = { 11, 23, 29, 37, 41, 43, 47, 53, 59 };
long long int factor[10];
scanf("%d", &max);
for (int i = 0; i < 9 && answer[i] <= max; i++) {
switch (answer[i]) {
case 11:
printf("23 * 89 = 2047 = ( 2 ^ 11 ) - 1\n");
break;
case 23:
printf("47 * 178481 = 8388607 = ( 2 ^ 23 ) - 1\n");
break;
case 29:
printf("233 * 1103 * 2089 = 536870911 = ( 2 ^ 29 ) - 1\n");
break;
case 37:
printf("223 * 616318177 = 137438953471 = ( 2 ^ 37 ) - 1\n");
break;
case 41:
printf("13367 * 164511353 = 2199023255551 = ( 2 ^ 41 ) - 1\n");
break;
case 43:
printf("431 * 9719 * 2099863 = 8796093022207 = ( 2 ^ 43 ) - 1\n");
break;
case 47:
printf("2351 * 4513 * 13264529 = 140737488355327 = ( 2 ^ 47 ) - 1\n");
break;
case 53:
printf("6361 * 69431 * 20394401 = 9007199254740991 = ( 2 ^ 53 ) - 1\n");
break;
case 59:
printf("179951 * 3203431780337 = 576460752303423487 = ( 2 ^ 59 ) - 1\n");
break;
}
}
return 0;
}
簡單粗暴版
大概10s以內的代碼, 里面的注釋能夠幫助理清思路。
// Copyright (c) 2015 HuangJunjie@SYSU(SNO:13331087). All Rights Reserved.
// sicily 1009: http://soj.sysu.edu.cn/1009
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
// get all prime numbers that is no more than num.
// @Param num: the max number that we want the primes less than.
// @return: a prime list.
vector<int> getPrime(int num) {
vector<int> prime;
prime.push_back(2);
for (int i = 3; i <= num; i+=2) {
bool isPrime = true;
for (int j = 0; j < prime.size(); j++) {
if (prime[j] * prime[j] > i) break;
if (i % prime[j] == 0) {
isPrime = false;
break;
}
}
if (isPrime) prime.push_back(i);
}
return prime;
}
int main() {
// gets all posible exponents.
vector<int> exponent = getPrime(63);
int max;
vector<long long int> factor;
scanf("%d", &max);
// exams the corresponding mersenne number for a exponent.
// if the mersenne is a composite number, outputs it.
for (int i = 0; i < exponent.size() && exponent[i] <= max; i++) {
long long int mersenne = (1LL << exponent[i]) - 1;
long long int temp = mersenne;
// counts the factors.
factor.clear();
for (long long int j = 3; j*j < temp; j += 2) {
if (temp%j == 0) {
factor.push_back(j);
temp /= j;
}
}
// if @temp is less than @mersenne, which means that mersenne has some
// factors, and temp is also a prime factor for it doesn't divide any
// numbers less than its square root.
if (temp < mersenne) factor.push_back(temp);
// factors exists means mersenne is composite. outputs it.
if (!factor.empty()) {
for (int j = 0; j < factor.size(); j++) {
if (j) printf(" * ");
printf("%lld", factor[j]);
}
printf(" = %lld = ( 2 ^ %d ) - 1\n", mersenne, exponent[i]);
}
}
return 0;
}
優(yōu)化版
此版本是參考http://www.cnblogs.com/mjc467621163/archive/2011/07/04/2097278.html
只針對符合的結果運算裹虫,可能剩下超級多的時間肿嘲。
// Copyright (c) 2015 HuangJunjie@SYSU(SNO:13331087). All Rights Reserved.
// sicily 1009: http://soj.sysu.edu.cn/1009
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int main() {
int max;
int answer[9] = { 11, 23, 29, 37, 41, 43, 47, 53, 59 };
long long int factor[10];
scanf("%d", &max);
for (int i = 0; i < 9 && answer[i] <= max; i++) {
long long int mersenne = (1LL << answer[i]) - 1;
long long int temp = mersenne;
memset(factor, 0, sizeof(factor));
int count = 0;
for (long long int j = 3; j*j < temp; j+=2) {
if (temp%j ==0) {
factor[count++] = j;
temp /= j;
}
}
if (temp < mersenne) factor[count++] = temp;
for (int j = 0; j < count; j++) {
if (j) printf(" * ");
printf("%lld", factor[j]);
}
printf(" = %lld = ( 2 ^ %d ) - 1\n", mersenne, answer[i]);
}
return 0;
}
以上兩個版本都存在不能檢驗重復因式的問題,所以對優(yōu)化版的因子判斷(21-28行)進行小改良
int count = 0;
for (long long int j = 3; j*j < temp; j += 2) {
if (temp%j == 0) {
while (temp%j == 0) {
factor[count++] = j;
temp /= j;
}
}
}
if (temp < mersenne) factor[count++] = temp;
參考
http://m.blog.csdn.net/blog/zhanweeleee/40949933
http://www.cnblogs.com/mjc467621163/archive/2011/07/04/2097278.html