求助丨Redraiment猜想
361
2024.10.13
2024.10.13
发布于 浙江

Redraiment猜想

redraiment在家极度无聊,于是找了张纸开始统计素数的个数。
设函数f(n)返回从1->n之间素数的个数。
redraiment发现:

f(1) = 0
f(10) = 4
f(100) = 25
...


满足g(m) = 17 * m2 / 3 - 22 * m / 3 + 5 / 3
其中m为n的位数。
他很激动,是不是自己发现了素数分布的规律了!
请你设计一个程序,求出1->n范围内素数的个数,来验证redraiment是不是正确的,也许还可以得诺贝尔奖呢。^_^


输入包括多组数据。
每组数据仅有一个整数n (1≤n≤100000000)。
输入以0结束


对于每组数据输入,输出一行,为1->n(包括n)之间的素数的个数。


输入:
1
10
65
100
0


输出:
0
4
18
25


有没有大佬来看看,想了两天了从短除法到埃拉托算法还是做不出来从超时到超内存

后面把数组范围改了加上短除又超时

数组e8次方要怎么解决,呜呜呜-------

附上源代码

#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#define MAX 1000000

unsigned char isPrime[(MAX / 8) + 1];  // 使用位数组压缩空间
long primeCount[MAX + 1];  // 存储每个数的素数个数

// 判断某个数是否为素数(通过位操作)
bool getPrime(long i) {
    return isPrime[i / 8] & (1 << (i % 8));
}

// 设置某个数为合数(通过位操作)
void setComposite(long i) {
    isPrime[i / 8] &= ~(1 << (i % 8));
}

// 埃拉托色尼筛法并预处理素数个数
void sieve() {
    // 初始化所有数为素数
    memset(isPrime, 0xFF, sizeof(isPrime)); // 将数组初始化为全1
    long i = 0;
    for (; i <= MAX; i++) {
        isPrime[i / 8] |= (1 << (i % 8));
    }

    // 埃拉托色尼筛法
    long iNsqrt = sqrt(MAX);
    long in = 2;
    for (; in <= iNsqrt; in++) {
        if (getPrime(in)) {
            long j = in * in;
            for (; j <= MAX; j += in) {
                setComposite(j);
            }
        }
    }

    // 预处理每个数的素数个数
    long ind = 2;
    for (; ind <= MAX; ind++) {
        primeCount[ind] = primeCount[ind - 1] + (getPrime(ind) ? 1 : 0);
    }
}

// 判断一个数是否为质数
int Isprime(int num) {
    if (num < 2) return 0; // 小于2的数不是质数
    if (num == 2) return 1; // 2是质数
    if (num % 2 == 0) return 0; // 其他偶数不是质数
    int iNum = 3;
    long inum  = sqrt(num);
    for (; iNum <= inum; iNum += 2) { // 只检查奇数因子
        if (num % iNum == 0) return 0;
    }
    
    return 1; // 是质数
}

int main() {
    sieve();  // 预处理MAX所有素数
    long iNum;

    while (scanf("%ld", &iNum) != EOF && iNum > 0) {
        if (iNum <= MAX) {
            printf("%ld\n", primeCount[iNum]);
        } else {
            long index = MAX + 1;
            long iNum3 = 0; 
            for (; index <= iNum; index++) { // 修正循环条件
                if (Isprime(index)) iNum3++;
            }
            printf("%ld\n", (primeCount[MAX] + iNum3));
        }
    }

    return 0;
}
评论 (2)