BJFU 1271 惊讶N

惊讶N

时间限制(C/C++):1000MS/3000MS          运行内存限制:65536KByte
总提交:150            测试通过:51

描述

大家都知道N的阶乘记作N!,就好像很惊讶,我就叫它惊讶N.
所以这题跟N!有关,给一个数N,求N!中所有质因数和

输入

多组测试数据,每组一行,每行有一个数字N(1<N<1000000)

输出

输出N!中所有质因数和

样例输入

2
3
4

样例输出

2
5
9

我这有三段代码:(傅总写的思路大概差不多。。这是他说的。。我是没看懂他代码...)

解法一:

#include<iostream>
#include<string.h>
#define N 1000010
using namespace std;
long long a[N];
int prime[N];
void get_prime(){
    memset(prime,0,sizeof(prime)); //prime = 0
    prime[0] = 1;
    prime[1] = 1;
    for(int i=2;i*i<=N;i++){
        for(int j = i;j * i <= N ; j++)
            prime[i*j] = 1;
    }
}
long long func(int n){
    if(!prime[n])
        return n;
    long long ans = 0;
    while(prime[n]){
        for(int i = 2;i * i <= n; i++){
            if(!prime[i] && n % i == 0){
                ans+=i;
                n/=i;
                break;
            }
        }
    }
    ans += n;
    return ans;
}
void compute(){
    get_prime();
    a[0] = 0;
    a[1] = 0;
    a[2] = 2;
    for(int i=3;i<N;i++)
        a[i] = a[i-1] + func(i);
}
int main(){
    int n;
    compute();
    while(cin>>n){
        cout<<a[n]<<endl;
    }
    return 0;
}
总结:时间复杂度和空间复杂度都很高,主要就是把答案存在数组里先算出来,其中后一项是前一项加上项数的素因子和。(求项数的素因子和写的很麻烦)。反正这段代码不太好。。。。

代码二:

#include <iostream>
#include <string.h>
#define N 1000010
long long ans[N];
using namespace std;
void compute(){
    memset(ans,0,sizeof(ans));
    for(int i=0;i<=N;i++)
        ans[i] = i;
    for(int i = 2;i * i <= N ; i++){
        for(int j = i; i * j <= N;j++)
            ans[i * j] = ans[i] + ans[j]; //*************
    }
    for(int i=2;i<N;i++)
        ans[i+1] +=ans[i];
}
int main(){
    int n;
    compute();
    while(cin>>n){
        cout<<ans[n]<<endl;
    }
    return 0;
}
总结:主要计算过程是在compute里。。先把答案数组赋值(其实是给素数赋值,因为合数部分在后面的循环里会被覆盖),根据算数基本定理,所有不是素数的数都可以用唯一的素数积序列表示,所以有了加标记的那一句。积的值是因子的和。(两重循环里的内容和素数筛选法有些像,i*j可以表示N之内的所有和数。i 和 j 要么是素数,要么是合数,如果是合数的话ans[]则是对应合数的素因子和,两项相加即可)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值