输入一个数n(n<=10000),输出第n个质数,要求运行时间不超过1000毫秒

特殊未来 2021-04-17 09:02:36
求大佬帮忙,注意时间一定要控制在1秒内
...全文
2202 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
特殊未来 2021-05-03
  • 打赏
  • 举报
回复
感谢大家的回复,虽然我家电脑还是有点裂开,反正先结了吧
xuanzhiruoshui 2021-04-26
  • 打赏
  • 举报
回复
这种问题,只考虑速度其实是很好过的,先写个程序计算素数,然后存数组,然后用这个数组实现找第n个素数就很简单了。 当然,需要多试几次,大概摸清楚,用例里面最大的n是多少。
源代码大师 2021-04-26
  • 打赏
  • 举报
回复
C和C++ 完整教程:https://blog.csdn.net/it_xiangqiang/category_10581430.html C和C++ 算法完整教程:https://blog.csdn.net/it_xiangqiang/category_10768339.html
  • 打赏
  • 举报
回复
是楼主自摆乌龙了~
冰思雨 2021-04-25
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char * argv[]) {
    printf("输入一个数n(n<=10000),输出第n个质数,要求运行时间不超过1000毫秒。\n");
    int n = 10000;
    scanf("%d",&n);
    if (n>10000) {
        printf("输入的n(%d)大于 10000 .\n", n);
        return 0;
    }
    
    int primes[10001] = {0};
    int flag = 0;
    for (int i=3; i<=10000; i++) {
        flag = 1;
        for (int j=2; j*j <= i; j++) {
            if (i%j == 0) {
                primes[i] = 0;
                flag = 0;
                break;
            }
        }
        if (flag){primes[i] = 1;}
    }
    
    printf("%s\n", primes[n] == 1 ? "true" : "false");
    
    return 0;
}
全算出来也不需要1秒钟的时间,所以,我先把所有素数都算出来,然后,直接输出即可。
自信男孩 2021-04-23
  • 打赏
  • 举报
回复
引用 23 楼 特殊未来 的回复:
[quote=引用 13 楼 早打大打打核战争 的回复:]稍微优化一下:

#include <stdio.h>
#include <math.h>

int main()
{
int n, pn[10000] = {2, 3, 5, 7, 11, 13, 17, 19};

for (int i = 21, j, p = (scanf("%d", &n), 8); p < n; i += 2)
{
for (j = 1; pn[j] <= (int)sqrt((float)i); j++)
if (!(i % pn[j])) {j = p; break;}
if (j < p) pn[p++] = i;
}
printf("%d\n", pn[n - 1]);

return 0;
}
裂开,3.322秒,还是超时[/quote]
用查表法呢,查表法试试呢,应该是没问题的
The 祺℡ 2021-04-23
  • 打赏
  • 举报
回复
最快的方法是: 程序初始化的時候先找到(n<=10000)個所有素數。然後cin>>n的時候直接cout<<a[n];
qzjhjxj 2021-04-22
  • 打赏
  • 举报
回复
你得卡循环计算的时间。
forever74 2021-04-22
  • 打赏
  • 举报
回复
该不会是把等你手工输入的时间都算上了吧?你把10000写进代码不输入了试试。
特殊未来 2021-04-22
  • 打赏
  • 举报
回复
引用 13 楼 早打大打打核战争 的回复:
稍微优化一下:

#include <stdio.h>
#include <math.h>

int main()
{
  int n, pn[10000] = {2, 3, 5, 7, 11, 13, 17, 19};

  for (int i = 21, j, p = (scanf("%d", &n), 8); p < n; i += 2)
  {
    for (j = 1; pn[j] <= (int)sqrt((float)i); j++)
      if (!(i % pn[j])) {j = p; break;}
    if (j < p) pn[p++] = i;
  }
  printf("%d\n", pn[n - 1]);

  return 0;
}
裂开,3.322秒,还是超时
特殊未来 2021-04-22
  • 打赏
  • 举报
回复
引用 11 楼 qzjhjxj 的回复:
[quote=引用 6 楼 特殊未来 的回复:][quote=引用 2 楼 qzjhjxj 的回复:]供参考:
#include<stdio.h>
//#include<time.h>

int is_prime(int n)
{
    if(n < 2) return 0;
	for (int j = 2;j*j <= n;j++){
	     if(n%j==0){
                return false;
             }
	}
	return 1;
}
int main()
{
	int n,s=0,i=2;
	scanf("%d",&n);
	while(s != n){
            if(is_prime(i)){
                s++;
            }
            i++;
	}
	printf("%d\n",i-1);
        
	return 0;
}
那个,我们有一个样例是10000,在把3楼的也加进去后,程序仍然需要3秒啊[/quote] 这是我机器上跑的结果:
//10000
//104729
//15.00ms请按任意键继续. . .

//10000
//104729
//16.00ms请按任意键继续. . .

//100000
//1299709
//234.00ms请按任意键继续. . .

//100000
//1299709
//218.00ms请按任意键继续. . .

//200000
//2750159
//625.00ms请按任意键继续. . .
[/quote]严重怀疑·是我家电脑太老了
特殊未来 2021-04-22
  • 打赏
  • 举报
回复
引用 9 楼 forever74 的回复:
那就祭起筛法试试:
#include <stdio.h>
int x[110000], prime[10000]; //第10000个素数还不到105000
int main()
{
	int n, k, i, j;
	for (i = 2; i < 110000; i++)x[i] = 1; //预备
	for (i = 2; i < 332; i++)
	{
		if (!x[i])continue; //合数跳过,找到下一个素数
		j = 2;
		while ((k = i * j++) < 110000)x[k] = 0;  //它的整数倍都是合数
	}
	for (i = 2, j = 0; i < 110000 && j < 10000; i++)
		if (x[i])prime[j++] = i;
	scanf("%d", &n);
	printf("%d\n", prime[n - 1]);
	return 0;
}
莫非是我家电脑太老了?
脆皮大雪糕 2021-04-21
  • 打赏
  • 举报
回复
看到问题就开写,写完发现进错区了,但既然花时间了就贴出来吧。 开个excel,用VBA写一个,我这运行稳定在50ms以内……

Private Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long
Dim lngPrimes(10000) As Long '1万个元素空间的数组用来存放1万个素数
Sub main()
    Dim i As Long '用来标记当前已经是第几个素数
    Dim lngTest As Long  '用来测试是否是素数的数
    Dim lngStartTime As Long
    lngStartTime = timeGetTime()
    i = 1
    lngPrimes(i) = 2 '第一个素数是2
    lngTest = 1 '测试数初始化为1,等下我们从3开始测
    Do While i < 10000 '没攒够1万个就继续算
        lngTest = lngTest + 2 '测试数第一次从3开始,后面每次都只测试奇数
        If testprime(lngTest, i) Then '如果测试数是素数
            i = i + 1 '素数计数加1
            lngPrimes(i) = lngTest
        End If
    Loop
    Debug.Print "第10000个素数:"; lngPrimes(10000), "耗时(毫秒):"; timeGetTime - lngStartTime
End Sub
'素数测试函数,输入被测试数,目前素数数组已经找到的素数总数,返回布尔值是否是素数
Private Function testprime(lngIn As Long, primecount As Long) As Boolean
    Dim a As Long, lngSqrt As Long
    testprime = False '默认返回false
    lngSqrt = Sqr(lngIn) '取一次测试数的开方,避免重复计算开方
    For a = 1 To primecount '挨个素数进行测试
        If CDbl(lngIn) / lngPrimes(a) = lngIn \ lngPrimes(a) Then Exit Function '如果被某个素数整除,啥也别说了,这个不是素数,直接退出
        If lngPrimes(a) > lngSqrt Then '如果测试除数已经超过测试数的开方了,没必要继续了
            testprime = True
            Exit Function
        End If
    Next
    testprime = True
End Function

movsd 2021-04-20
  • 打赏
  • 举报
回复
你们的代码都没有这个快

	const int p[]=
	{
		2,3,5,7,11,13,17,19,23,29,
		31,37,41,43,47,53,59,61,67,71,
		73,79,83,89,97,101,103,107,109,113,
		127,131,137,139,149,151,157,163,167,173,
		179,181,191,193,197,199,211,223,227,229,
		233,239,241,251,257,263,269,271,277,281,
		283,293,307,311,313,317,331,337,347,349,
		353,359,367,373,379,383,389,397,401,409,
		419,421,431,433,439,443,449,457,461,463,
		467,479,487,491,499,503,509,521,523,541,
		547,557,563,569,571,577,587,593,599,601,
		607,613,617,619,631,641,643,647,653,659,
		661,673,677,683,691,701,709,719,727,733,
		739,743,751,757,761,769,773,787,797,809,
		811,821,823,827,829,839,853,857,859,863,
		877,881,883,887,907,911,919,929,937,941,
		947,953,967,971,977,983,991,997,1009,1013,
		1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,
		1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,
		1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,
		1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,
		1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,
		1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,
		1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,
		1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,
		1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,
		1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,
		1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,
		1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,
		1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,
		1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,
		2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,
		2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,
		2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,
		2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,
		2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,
		2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,
		2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,
		2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,
		2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,

		// 省略一部分数据。。。

		103391,103393,103399,103409,103421,103423,103451,103457,103471,103483,
		103511,103529,103549,103553,103561,103567,103573,103577,103583,103591,
		103613,103619,103643,103651,103657,103669,103681,103687,103699,103703,
		103723,103769,103787,103801,103811,103813,103837,103841,103843,103867,
		103889,103903,103913,103919,103951,103963,103967,103969,103979,103981,
		103991,103993,103997,104003,104009,104021,104033,104047,104053,104059,
		104087,104089,104107,104113,104119,104123,104147,104149,104161,104173,
		104179,104183,104207,104231,104233,104239,104243,104281,104287,104297,
		104309,104311,104323,104327,104347,104369,104381,104383,104393,104399,
		104417,104459,104471,104473,104479,104491,104513,104527,104537,104543,
		104549,104551,104561,104579,104593,104597,104623,104639,104651,104659,
		104677,104681,104683,104693,104701,104707,104711,104717,104723,104729,
	};
	printf("%d",p[9999]);
自信男孩 2021-04-20
  • 打赏
  • 举报
回复
sqrt

这个函数耗时,建议改成j * j <= n这种形式

自信男孩 2021-04-20
  • 打赏
  • 举报
回复
#include<stdio.h>
#include <math.h>

int is_prime(int n)
{
if(n < 2)
return 0;

for (int j = 2; j <= (int)sqrt(n);j++){
if(n%j==0){
return 0;
}
}
return 1;
}
int main(void)
{
int n, s=1, i = 3;

scanf("%d",&n);
if (n == 1) {
printf("2\n");
return 0;
}

while (s != n) {
if(is_prime(i))
s++;
i += 2;
}
printf("%d\n", i);

return 0;
}

供参考~

根据质数一定是奇数,这样推定再加上sqrt减少循环次数,提高运算速率~

自信男孩 2021-04-20
  • 打赏
  • 举报
回复
   for (int j = 2;j*j <= n;j++){
if(n%j==0){
return false;
}
}

改成

   for (int j = 2;j*j <= sqrt(n);j++){    //减少运行次数,比如n=101,那么可能需要运行101-2次吧, 使用sqrt之后,运行10-2次。减少循环次数,降低时间复杂度
if(n%j==0){
return false;
}
}

供参考~
yiyoyiyocc 2021-04-20
  • 打赏
  • 举报
回复
我的回复收到了吗?怎么感觉被吞了
自信男孩 2021-04-20
  • 打赏
  • 举报
回复
引用 17 楼 movsd 的回复:
你们的代码都没有这个快

const int p[]=
{
2,3,5,7,11,13,17,19,23,29,
31,37,41,43,47,53,59,61,67,71,
73,79,83,89,97,101,103,107,109,113,
127,131,137,139,149,151,157,163,167,173,
179,181,191,193,197,199,211,223,227,229,
233,239,241,251,257,263,269,271,277,281,
283,293,307,311,313,317,331,337,347,349,
353,359,367,373,379,383,389,397,401,409,
419,421,431,433,439,443,449,457,461,463,
467,479,487,491,499,503,509,521,523,541,
547,557,563,569,571,577,587,593,599,601,
607,613,617,619,631,641,643,647,653,659,
661,673,677,683,691,701,709,719,727,733,
739,743,751,757,761,769,773,787,797,809,
811,821,823,827,829,839,853,857,859,863,
877,881,883,887,907,911,919,929,937,941,
947,953,967,971,977,983,991,997,1009,1013,
1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,
1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,
1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,
1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,
1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,
1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,
1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,
1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,
1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,
1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,
1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,
1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,
1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,
1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,
2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,
2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,
2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,
2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,
2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,
2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,
2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,
2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,
2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,

// 省略一部分数据。。。

103391,103393,103399,103409,103421,103423,103451,103457,103471,103483,
103511,103529,103549,103553,103561,103567,103573,103577,103583,103591,
103613,103619,103643,103651,103657,103669,103681,103687,103699,103703,
103723,103769,103787,103801,103811,103813,103837,103841,103843,103867,
103889,103903,103913,103919,103951,103963,103967,103969,103979,103981,
103991,103993,103997,104003,104009,104021,104033,104047,104053,104059,
104087,104089,104107,104113,104119,104123,104147,104149,104161,104173,
104179,104183,104207,104231,104233,104239,104243,104281,104287,104297,
104309,104311,104323,104327,104347,104369,104381,104383,104393,104399,
104417,104459,104471,104473,104479,104491,104513,104527,104537,104543,
104549,104551,104561,104579,104593,104597,104623,104639,104651,104659,
104677,104681,104683,104693,104701,104707,104711,104717,104723,104729,
};
printf("%d",p[9999]);

以空间换取时间,牺牲空间,换取时间;如果确实没办法达标1000ms,可以考虑楼上这位的策略,做到极致
  • 打赏
  • 举报
回复
稍微优化一下:

#include <stdio.h>
#include <math.h>

int main()
{
int n, pn[10000] = {2, 3, 5, 7, 11, 13, 17, 19};

for (int i = 21, j, p = (scanf("%d", &n), 8); p < n; i += 2)
{
for (j = 1; pn[j] <= (int)sqrt((float)i); j++)
if (!(i % pn[j])) {j = p; break;}
if (j < p) pn[p++] = i;
}
printf("%d\n", pn[n - 1]);

return 0;
}

加载更多回复(12)

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧