庞果网幸运数,一解,失败的例子吧

来源:互联网 发布:寻求淘宝合作伙伴 编辑:程序博客网 时间:2024/04/30 01:04

   如果一个数各个数位上的数字之和是质数,并且各个数位上的数字的平方和也是质数,则称它为幸运数。 给定x,y,求x,y之间( 包含x,y,即闭区间[x,y])有多少个幸运数。 例如1到20之间有4个幸运数,它们是11,12,14,16,像因为1+1 = 2是质数,1^2 + 1^2 = 2也是质数等等。 给定函数原型,其中1<=x<=y<=1000000000,请完成函数,实现上述功能。

以下代码可以实现,但对1-1000000000的估计有20多秒才会返回结果。


int prime_num[]={0,0,2,3,0,5,0,7,0,0,0,11,0,13,0,0,0,17,0,19,0,0,0,23,0,0,0,0,0,29,0,31,0,0,0,0,0,37,0,0,0,41,0,43,0,0,0,47,0,0,0,0,0,53,0,0,0,0,0,59,0,61,0,0,0,0,0,67,0,0,0,71,0,73,0,0,0,0,0,79,0,0,0,83,0,0,0,0,0,89,0,0,0,0,0,0,0,97,0,0,0,101,0,103,0,0,0,107,0,109,0,0,0,113,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,131,0,0,0,0,0,137,0,139,0,0,0,0,0,0,0,0,0,149,0,151,0,0,0,0,0,157,0,0,0,0,0,163,0,0,0,167,0,0,0,0,0,173,0,0,0,0,0,179,0,181,0,0,0,0,0,0,0,0,0,191,0,193,0,0,0,197,0,199,0,0,0,0,0,0,0,0,0,0,0,211,0,0,0,0,0,0,0,0,0,0,0,223,0,0,0,227,0,229,0,0,0,233,0,0,0,0,0,239,0,241,0,0,0,0,0,0,0,0,0,251,0,0,0,0,0,257,0,0,0,0,0,263,0,0,0,0,0,269,0,271,0,0,0,0,0,277,0,0,0,281,0,283,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,307,0,0,0,311,0,313,0,0,0,317,0,0,0,0,0,0,0,0,0,0,0,0,0,331,0,0,0,0,0,337,0,0,0,0,0,0,0,0,0,347,0,349,0,0,0,353,0,0,0,0,0,359,0,0,0,0,0,0,0,367,0,0,0,0,0,373,0,0,0,0,0,379,0,0,0,383,0,0,0,0,0,389,0,0,0,0,0,0,0,397,0,0,0,401,0,0,0,0,0,0,0,409,0,0,0,0,0,0,0,0,0,419,0,421,0,0,0,0,0,0,0,0,0,431,0,433,0,0,0,0,0,439,0,0,0,443,0,0,0,0,0,449,0,0,0,0,0,0,0,457,0,0,0,461,0,463,0,0,0,467,0,0,0,0,0,0,0,0,0,0,0,479,0,0,0,0,0,0,0,487,0,0,0,491,0,0,0,0,0,0,0,499,0,0,0,503,0,0,0,0,0,509,0,0,0,0,0,0,0,0,0,0,0,521,0,523,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,541,0,0,0,0,0,547,0,0,0,0,0,0,0,0,0,557,0,0,0,0,0,563,0,0,0,0,0,569,0,571,0,0,0,0,0,577,0,0,0,0,0,0,0,0,0,587,0,0,0,0,0,593,0,0,0,0,0,599,0,601,0,0,0,0,0,607,0,0,0,0,0,613,0,0,0,617,0,619,0,0,0,0,0,0,0,0,0,0,0,631,0,0,0,0,0,0,0,0,0,641,0,643,0,0,0,647,0,0,0,0,0,653,0,0,0,0,0,659,0,661,0,0,0,0,0,0,0,0,0,0,0,673,0,0,0,677,0,0,0,0,0,683,0,0,0,0,0,0,0,691,0,0,0,0,0,0,0,0,0,701,0,0,0,0,0,0,0,709,0,0,0,0,0,0,0,0,0,719,0,0,0,0,0,0,0,727,0,0};//729以内素数,(1000000000以内最大:9个9每位平方相加得729)const int square_num[]={0,1,4,9,16,25,36,49,64,81};int lucky(int x,int y) {int iLuckyNumber = 0;int n=0;int i;for (n = x; n <= y; n ++){int num = n;int numArr[10] = {0};for (i = 0; i <10; ++i){numArr[i] = num % 10;if((num /=10)==0)break;}int iAddSum = numArr[0] + numArr[1] + numArr[2] + numArr[3] + numArr[4] + numArr[5] +numArr[6] + numArr[7] + numArr[8] + numArr[9];int isqrtSum =square_num[numArr[0]]+square_num[numArr[1]]+square_num[numArr[2]]+square_num[numArr[3]]+square_num[numArr[4]]++square_num[numArr[5]]+square_num[numArr[6]]+square_num[numArr[7]]+square_num[numArr[8]]+square_num[numArr[9]];if(prime_num[iAddSum]&&prime_num[isqrtSum]){//printf("number =%d\n" , n);++iLuckyNumber ;}}return iLuckyNumber;}

后找到个取巧的方法:就是把整个1-1000000000划分区间,对每个区间先求出来,对输入[x,y]按区间分割,对区间内的直接加。。不到一个区间的再调用以上方法算出来,原来区间大小取5000000,我机器上可以,最大2点多秒,但提交上去貌似超时了,只有再往下划分了,区间大小1000000应该就可以了。

int luck_num=5000000;int  luck[]={463448,433757,458104,443231,459072,446850,448125,438665,452604,443181,449366,436941,442002,428857,445764,429509,437404,413814,431150,407235,458104,443232,451819,447480,460081,453735,442624,433906,445129,441962,451461,447361,443647,435141,437442,430637,453711,432720,434051,410451,459072,446851,460081,453735,460801,441563,444240,436895,460539,453361,445568,434207,448352,432096,456597,440796,444154,413277,437731,404888,448125,438665,442624,433906,444240,436895,438344,439080,438767,437717,441397,428076,436874,418500,439758,421916,441127,407975,427107,394485,452604,443182,445129,441962,460539,453360,438767,437717,451245,441228,455853,440994,445990,424007,435153,409748,450747,417457,429705,398543,449366,436941,451461,447361,445568,434207,441397,428076,455853,440994,441519,415305,439154,409389,448590,417808,436090,391486,422226,380794,442002,428858,443647,435141,448352,432096,436874,418500,445990,424008,439154,409389,439402,399550,427837,397793,420090,374830,412119,372708,445764,429509,437442,430637,456597,440796,439758,421915,435153,409748,448590,417807,427837,397793,421771,391244,428814,391173,405593,374951,437404,413814,453711,432720,444154,413278,441127,407975,450747,417457,436090,391486,420090,374830,428814,391173,406459,364263,393789,354934,431150,407235,434051,410451,437731,404888,427107,394486,429705,398543,422226,380794,412119,372708,405593,374951,393789,354934,381876,353391};//luck_double用来处理区间点重复计算的问题的int luck_double[]={0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0};int lucky_2(int x,int y);int lucky(int x,int y) {int iLuckyNum=0;int first_num=(x/luck_num);int first_1=first_num*luck_num;//int first_2=x%luck_num;int last_num=(y/luck_num);int last_1=last_num*luck_num;//int last_2=y%luck_num;int i=0;for(i=first_num ; i<last_num ; ++i){iLuckyNum+=luck[i]-luck_double[i];}iLuckyNum+=luck_double[first_num]+luck_double[last_num-1];//printf("%d,%d,%d,%d,%d\n",first_1,last_1,iLuckyNum,lucky_2(first_1,x),lucky_2(last_1,y));if(first_1==last_1)return lucky_2(x,y);//luck_2就是上面的luckif(x-first_1>luck_num/2)iLuckyNum-=lucky_2(first_1,x);else{iLuckyNum=iLuckyNum-luck[first_num]+luck_double[first_num]+lucky_2(x,first_1+luck_num-1);}if(y-last_1>luck_num/2)iLuckyNum+=lucky_2(last_1+1,y);else{iLuckyNum=iLuckyNum+luck[last_num]-luck_double[last_num-1]-lucky_2(y,last_1+luck_num);}return iLuckyNum;}
太取巧了,个人感觉。算法无关。。。唉。。再想下有什么其他的方法没?