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

   如果一个数各个数位上的数字之和是质数,并且各个数位上的数字的平方和也是质数,则称它为幸运数。 给定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就是上面的luck

	if(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;
	
}
太取巧了,个人感觉。算法无关。。。唉。。再想下有什么其他的方法没?






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值