刚才有人问了道题,求第一个因数个数超过500的三角数
原题如下:
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
看了一下,第一反应是枚举,但是写了才发现,并没有这么简单,第一个有500+因子的数很大,如果不进行优化根本无法得到答案(或者可以得到,但在微型机下计算时间过于长),所以,既然要优化,那么就得看看数的特征了,通过数论可以知道,数的因子个数以及数本身的关系如下:
N=2^t1 * 3 ^t2 *...* m^tx 即将N分解为素数的积,那么其因子个数即为(t1+1)*(t2+1)*......*(tx+1);
例如:
48=2^4 * 3^1 所以其因子个数为(4+1)*(1+1)=10 为1、2、3、4、6、8、12、16、24、48 十个
105=3^1 * 5^1 * 7^1 所以其因子个数为(1+1)*(1+1)*(1+1)=8 为1、3、5、7、15、21、35、105 八个
以上结论很简单,证明略
回归正题,有以上结论后我们就可以大大减少计算量,不过首先需要创建一个素数表,这个会浪费一定空间,具体代码实现如下:
#include"stdio.h" #include"math.h" int isSushu(long b) //判断是否为素数 { long i=0; int j=1; if(b==2) return 1; for(i=2;i<=(int)sqrt(b);i++) if(b%i==0){ j=0; break; } return j; } int main() { long i=0,j=0,k=0,s[1000],b[1000]={0},n=0,m,count; for(i=2;i<=1000;i++) //创建素数表 if(isSushu(i)) s[j++]=i; for(i=1;count<500;i++) { count=1; m=(n+=i); for(k=0;k<j && m>1;k++) { while(m%s[k]==0) { m/=s[k]; b[k]++; } count*=(b[k]+1); b[k]=0; } } printf("1+2+..+%ld=%ld,有%ld个因子\n",i-1,n,count); return 0; }
运行结果为:1+2+..+12375=76576500,有576个因子
以上代码在VC下运行只需大约500ms,对于ACM的环境应该可以AC掉。