题目1207:质因数的个数
时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:10110
解决:3288
-
题目描述:
-
求正整数N(N>1)的质因数的个数。相同的质因数需要重复计算。如120=2*2*2*3*5,共有5个质因数。
-
输入:
-
可能有多组测试数据,每组测试数据的输入是一个正整数N,(1<N<10^9)。
-
输出:
-
对于每组数据,输出N的质因数的个数。
-
样例输入:
-
120
-
样例输出:
-
5
-
提示:
-
注意:1不是N的质因数;若N为质数,N是N的质因数。
-
来源:
-
2007年清华大学计算机研究生机试真题
天哪,这绝对是我做过的经历最丰富的一道题了,如下:
这承载着一个小白的成长过程。。。。。
489152kb的那版代码,我开了个10^8个整数的数组,本来开的是10^9的,但是编译器看不下去了,告诉我数组too large。内存既然超了,我试着改小一点,因为确实不需要那么多的素数。实际上,对于n,他至多有一个大于等于sqrt(n)的因数,否则相乘会超过n,所以数组开成10万的就够了。
这是超时那一版代码:
#include <cstdio> #define N 4000000 using namespace std; bool mark[N]={0}; int prime[N]; int size=0; void init() { for(int i=2;i<N;i++){ if(!mark[i]){ prime[size++]=i; for(int j=i;j<N;j+=i){ mark[j]=true; } } } } bool isprime(int n) { for(int i=0;i<size;i++){ if(prime[i]==n) return true; } return false; } int main() { int n; init(); while(scanf("%d",&n)!=EOF){ int cnt=0; int i=0; int flag=0; while((!isprime(n))&&(i<size)){ if(!flag) flag=1; while(n%prime[i]==0){ n/=prime[i]; cnt++; } i++; } if(flag==0) printf("1\n"); else printf("%d\n",cnt+1); } return 0; } /************************************************************** Problem: 1207 User: cjf1699 Language: C++ Result: Time Limit Exceed ****************************************************************/
我尝试利用isprime()函数对每次得来的n进行判断是否为素数,若是,跳出循环。虽然我把数组开到400w,保证了10^9以内的正整数的素因数一定被mark过,但 isprime()可能耗时过长,毕竟每次都要执行,超时了。于是我舍弃了 isprime(),简化while条件,用退出循环时n是否为1来判断,若否,那也只可能是仅仅再加上一个(≥sqrt(n)的)素因数,若是,那就是了,输出cnt即可。这时,为了进一步缩短时间,我把init()里的j=i改成了j=i*i,结果RE了。。。不懂,也不是long long的问题。j大于n时自己不要就终止循环了吗?也不会数组越界啊,后来一进调试,在崩溃的地方看了一下j的值才明白,i*i过大越界后,就会变成一个负值给j!而不是想象的一个大数!负数当然也小于N了!于是,,忘了有符号数这一点,悲剧了。。。
改成unsigned(或还用j=i),一切妥妥的。
#include <cstdio> #define N 100001 using namespace std; bool mark[N]={0}; unsigned int prime[N]; int size=0; void init() { for(unsigned int i=2;i<N;i++){ if(!mark[i]){ prime[size++]=i; for(unsigned int j=i*i;j<N;j+=i){ mark[j]=true; } } } } int main() { int n; init(); while(scanf("%d",&n)!=EOF){ int cnt=0; int i=0; while(i<size){ while(n%prime[i]==0){ n/=prime[i]; cnt++; } if(n==1) break; i++; } if(n!=1) printf("%d\n",cnt+1); else printf("%d\n",cnt); } return 0; }
再次证明了一点,如果RE,那基本就是数组越界了........**************************************************
坚持,而不是打鸡血~