在解决PackingRectangles这个问题的时候我强调枚举时要“将粗暴进行到底”,但并不是说可以无限度“粗暴”,当粗暴会导致TLE时,适当地构造解空间往往能大大优化程序的执行时间。
The number 151 is a prime palindrome because it is both a prime number and a palindrome (it is the same number when read forward as backward). Write a program that finds all prime palindromes in the range of two supplied numbers a and b (5 <= a < b <= 100,000,000); both a and b are considered to be within the range .
区间上限是1亿,如果我们直接枚举所有数据并检验是否是回文和素数会超时,实际上我们可以先构造出所有的回文数再检测他们是否是素数,n以内的回文数是很稀疏的,构造回文时我们只需枚举各个数位就可以了,这可以用o(√n)时间完成,另外检测n是否是素数的时间是o(√n),所以我们得到了一个o(n)的方法。
进化:
通过PackingRectangles和此问题,我们涉及到了构造和枚举的问题,过度构造会增加编程的复杂度,过度枚举又会超时,这就需要贴切的时间分析来选择了。在可接受的时间之内尽量减少构造,保持K.I.S.S(keep it simple and stupid)原则是个很好的方法。
点击查看我的程序源码:
/* ID: ******* LANG: C++ TASK: pprime */ #include<stdio.h> #include<stdlib.h> int a,b; FILE *fin,*fout; typedef struct{ int digital[9]; }Num; bool isPrime(int n){ int i; for(i=2;i*i<=n;i++) if(n%i==0) return false; return true; } void createPalinAndTest(int n,int L,Num num){//构造长度L的回文数 int i; if(L%2==0&&n>L/2 || L%2==1&&n>L/2+1){ //利用前一半构造整个回文数并且检测是否是素数 for(i=n;i<=L;i++) num.digital[i-1]=num.digital[1+L-i-1]; int t=1,N=0; for(i=0;i<L;i++){ N+=t*num.digital[i]; t*=10; } if(N<=b&&N>=a&&isPrime(N)){ fprintf(fout,"%d\n",N); } return; } for(i=0;i<=9;i++){ if(n==1&&i==0)continue;//首位不得为0 num.digital[n-1]=i; createPalinAndTest(n+1,L,num); } return; } int main(){ fin=fopen("pprime.in","r"); fout=fopen("pprime.out","w"); fscanf(fin,"%d %d",&a,&b); int i; Num num; for(i=1;i<=8;i++) createPalinAndTest(1,i,num); return 0; }
2019年10月01日 08:49
Printing notebook is very great idea. It will make notebook more beautiful and attractive. Today i found another idea to hack insta account and it is very safe.