sicily_1009 Mersenne Composite N

题目

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


题目大意

找出指数为63或以下的不是素数的梅森数。

思路

  1. 有限小个数答案的问题,效率最高的是枚举所有可能的答案,也就是所谓的直接打表。(然而有作弊的嫌疑)
  2. 建立好素数表,然后从中筛选。(然而那么大量数据的表,还没建好都TLE了)
  3. 简单粗暴地对每个数进行质因数分解。(然而一定会TLE)
  4. 只针对符合答案的情况进行计算。(其实这样子和打表没有什么区别)

代码

直接打表版

网上说算到59就够了,是因为$2^{61}-1$是一个梅森素数,这里不用输出。

// 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;
}

优化版

此版本是参考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;
}

以上两个版本都存在不能检验重复因式的问题,所以对优化版的因子判断(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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,355评论 0 23
  • 昨夜睡梦中又有些抽筋,只是肌肉作痛,本不想再跑,偷懒一天,不过还是坚持去跑了。去的路上见一猫自在的卧于路边车的车顶...
    goldfish2017阅读 269评论 0 0
  • 现在的我们都是处于亚健康状态,没有一个人敢肯定的说“我没病”这三个字。外表的健康不代表内在的零件已经脱落或衰竭。 ...
    PXX秘密之地阅读 274评论 0 0
  • 她总对人说自己最喜欢的点心是汤圆。 在北方他们都管它叫元宵,她还是喜欢从小习惯了的名字。 汤圆和元宵有什么样的区别...
    Lain_M阅读 900评论 7 5
  • 158家已开始2016校招名企列表 互联网(35家) 携程:http://pages.ctrip.com/xyzp...
    丁叮当ss阅读 829评论 0 2