Time Limit: 10 second
Memory Limit: 2 MB

问题描述

完全数又称完数、完美数、完备数,是一些特殊的自然数,它所有真因子(即除自己以外的因子)的和等于它本身。例如:6=1+2+3,6是一个完数。
    

至今为止,人类共发现了46个完数,由于简单类型的数据范围有限,所以仅能求出前n(n<=8)个完数。
  

 

Input

一个整数n

Output

有n行,输出前n个完数,每个数占一行

Sample Input

3

Sample Output

6
28
496

【题解】

如果直接暴力求解 会超时。10s都不够用。

这题考的是数论。有点变态。

完全数和梅森数素数有一个一一对应的关系

即对于一个梅森素数mp = 2^p - 1,必有 一个完全数 2^(p-1) * mp;

比如:p=3
Mp=2^3-1=7也是素数
则有完全数2^(3-1)*(2^3-1)=4*7=28

平台很奇怪,我用lld输出,输出来的结果是对的,在平台上却显示错误,后来我没用lld输出,一位一位地存入int数组中,再一位一位地输出。

【代码】

#include <cstdio>
#include <cmath>

const int maxn = 1000,maxl = 1000;

int num = 0,n;

void input_data()
{
    scanf("%d",&n);
}

bool can(long long  x) //判断x是否为质数
{
    if (x < 2) return false;
    int d = sqrt(x);
    for (int i = 2;i <=d;i++)
        if ( (x % i) == 0)
            return false;
    return true;
}

void get_ans()
{
    int p = 1;
    while (num != n) //如果还没有找到所需的数目就继续找。
        {
            long long int  mp = 1;
            for (int i = 1;i <= p;i++) //算2^p
                mp = mp*2;
            mp--;
            if (can(mp)) //如果这个梅森数是质数
                {
                    num++;
                    long long  int t = 1;
                    for (int i = 1;i <= p-1;i++)
                        t = t * 2;
                    t = t * mp; //算出完全数
                    int temp[maxl]; //把这个完全数一位一位地存入int数组;
                    int i = 0;
                    while (t > 0)
                    {
                        temp[++i] = t % 10;
                        t = t /10;
                    }
                    for (int j = i;j >=1;j--) //再一位一位输出
                        printf("%d",temp[j]);
                    printf("\n");
                }
            p++;
        }
}

int main()
{
    input_data();
    get_ans();
    return 0;
}