九度1207:质因数的个数

来源:互联网 发布:自动关注软件源码 编辑:程序博客网 时间:2024/05/22 02:05
题目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 4000000using 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 100001using 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,那基本就是数组越界了........

**************************************************

坚持,而不是打鸡血~

原创粉丝点击