描述
现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度。如果左右有等距离长度素数,则输出左侧的值及相应距离。
如果输入的整数本身就是素数,则输出该素数本身,距离输出0
如果输入的整数本身就是素数,则输出该素数本身,距离输出0
-
输入
-
第一行给出测试数据组数N(0<N<=10000)
接下来的N行每行有一个整数M(0<M<1000000),
输出
-
每行输出两个整数 A B.
其中A表示离相应测试数据最近的素数,B表示其间的距离。
样例输入
-
3 6 8 10
样例输出
-
5 1 7 1 11 1
My Solution1:普遍的做法。需要的时间稍微多一点。在OJ上运行时间为72ms(空间232)。
- #include<stdio.h>
- #include<stdlib.h>
- int isPrime(int num)
- {
- if(num==1)return 0;
- for(int i=2;i*i<=num;i++)
- if(num%i==0)
- return 0;
- return 1;
- }
- int main()
- {
- int n,num,numUp,numDown,deltUp,deltDown;
- scanf("%d",&n);
- while(n--)
- {
- scanf("%d",&num);
- if(isPrime(num))//本身是素数,后面就不用了
- printf("%d 0\n",num);
- else
- {
- numUp=numDown=num;
- while(!isPrime(numUp))
- {
- numUp+=1;
- }
- while(!isPrime(numDown)&&numDown>0)//边界条件,否则不能通过
- {
- numDown-=1;
- }
- deltUp = numUp-num;
- deltDown = num-numDown;
- if(numDown==0)//特殊情况:左边没有找到
- printf("%d %d\n",numUp,deltUp);
- else if(deltUp>=deltDown)//输出距离小的, 相等则左
- printf("%d %d\n",numDown,deltDown);
- else
- printf("%d %d\n",numUp,deltUp);
- }
- }
- //system("PAUSE");
- return 0;
- }
#include<stdio.h> #include<stdlib.h> int isPrime(int num) { if(num==1)return 0; for(int i=2;i*i<=num;i++) if(num%i==0) return 0; return 1; } int main() { int n,num,numUp,numDown,deltUp,deltDown; scanf("%d",&n); while(n--) { scanf("%d",&num); if(isPrime(num))//本身是素数,后面就不用了 printf("%d 0\n",num); else { numUp=numDown=num; while(!isPrime(numUp)) { numUp+=1; } while(!isPrime(numDown)&&numDown>0)//边界条件,否则不能通过 { numDown-=1; } deltUp = numUp-num; deltDown = num-numDown; if(numDown==0)//特殊情况:左边没有找到 printf("%d %d\n",numUp,deltUp); else if(deltUp>=deltDown)//输出距离小的, 相等则左 printf("%d %d\n",numDown,deltDown); else printf("%d %d\n",numUp,deltUp); } } //system("PAUSE"); return 0; }
My Solution2:花了好一会时间才完成,用筛选法建立素数表。用空间换时间。在OJ上运行时间为40ms(空间4136)。
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #define MAX 1000010
- int table[MAX];
- //筛选法建立素数表: 0为素数, 1为非素数
- void buildPrimeTable()
- {
- table[1]=1;//第0个不用
- for(int i=2;i*i<MAX;i++)
- if(!table[i])//不是素数的跳过
- for(int j=i*i;j<MAX;j+=i)
- table[j]=1; //包含因子i的不是素数,标记为1
- }
- int main()
- {
- buildPrimeTable();
- int n,num,numUp,numDown;
- scanf("%d",&n);
- while(n--)
- {
- scanf("%d",&num);
- if(table[num]==0)
- printf("%d 0\n",num);
- else
- {
- numUp=numDown=num;
- while(table[numUp]!=0)
- numUp++;
- while(table[numDown]!=0&&numDown>0)
- numDown--;
- if(numDown==0)//如果超过下线
- printf("%d %d\n",numUp,numUp-num);
- else if(numUp-num>=num-numDown)
- printf("%d %d\n",numDown,num-numDown);
- else
- printf("%d %d\n",numUp,numUp-num);
- }
- }
- //system("PAUSE");
- return 0;
- }
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX 1000010 int table[MAX]; //筛选法建立素数表: 0为素数, 1为非素数 void buildPrimeTable() { table[1]=1;//第0个不用 for(int i=2;i*i<MAX;i++) if(!table[i])//不是素数的跳过 for(int j=i*i;j<MAX;j+=i) table[j]=1; //包含因子i的不是素数,标记为1 } int main() { buildPrimeTable(); int n,num,numUp,numDown; scanf("%d",&n); while(n--) { scanf("%d",&num); if(table[num]==0) printf("%d 0\n",num); else { numUp=numDown=num; while(table[numUp]!=0) numUp++; while(table[numDown]!=0&&numDown>0) numDown--; if(numDown==0)//如果超过下线 printf("%d %d\n",numUp,numUp-num); else if(numUp-num>=num-numDown) printf("%d %d\n",numDown,num-numDown); else printf("%d %d\n",numUp,numUp-num); } } //system("PAUSE"); return 0; }
总结:
1. 要充分考虑边界情况。
对于第一种解法,考虑当输入的数为1时,向下到0就越界了,此时只能向上为2。
对于第二种解法,考虑当输入为999999时,此时最近的素数为1000003。所以定义table的大小时要到1000010最好。
2. 可以合并的要合并,不能合并的单独出来。
最开始写的时候,把左右距离相等的情况给分出来了写出if(deltUp==deltDown&&num==numDown)。完全没有必要。
该提前的要提前。如果是素数,后面的可以全部不用判断。
3. 关于筛选法建立素数表。
http://blog.csdn.net/code_pang/article/details/8022302
以前不知道有这个方法,确实很方便。就是用已知的素数,从前往后相加进行填充。