九度1207:质因数的个数

题目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,那基本就是数组越界了........

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

坚持,而不是打鸡血~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值