因子和

因子和

Accepted : 36 Submit : 263
Time Limit : 4000 MS Memory Limit : 65536 KB

题目描述

如果b能整除a,我们称b为a的因子。现在假设n的所有因子和为f(n);
给你两个整数a,b,(0 ≤ a ≤ b ≤ 5000000);
请你求出所有满足a ≤ i ≤ b的f(i)的和;
例如a=1,b=6,那么你就需要计算f(1)+f(2)+f(3)+f(4)+f(5)+f(6)。
我们规定f(0)=0;

输入

不超过2000个样例,每个样例占一行,为两个整数a,b;a=b=0时表示输入结束。

输出

每个样例输出一个整数,占一行。

样例输入
1 1
6 6
1 6
0 0

样例输出
1
12
33

求n的因数和,由任意一个正整数可以由素数相乘得到,n = p1^x1 * p2^x2 * p3^x3.......;
得到因数和为 ans = (p1^(x1+1)-1) / ( p1 - 1 )  *  (p2^(x2+1)-1) / (p2-1)  *  (p3^(x3+1)-1) / (p3-1)........  可推导出说有因数和
#include <stdio.h>
#include <string.h>
int a[5000001] ;
int b[5000001] ;
int check[5000001] ;
int tot = 0 ;
void f()
{
    memset(check,0,sizeof(check));
    int i , j ;
    for(i = 2 ; i <= 5000000 ; i++)
    {
        if( !check[i] )
            a[tot++] = i ;
        for(j = 0 ; j < tot ; j++)
        {
            if( i*a[j] > 5000000 )
                break;
            check[i*a[j]] = 1 ;
            if( i % a[j] == 0 )
                break;
        }
    }
}
__int64 F(int a,int b)
{
    int i , j ;
    __int64 num = 1 ;
    for(i = 0 ; i < b ; i++)
        num *= a ;
    return num ;
}
__int64 ans[5000001] ;
int main()
{
    f() ;
    int i , j , k , n ;
    for(i = 1 ; i <= 5000000 ; i++)
        ans[i] = 1 ;
    ans[0] = 0 ;
    for(i = 2 ; i <= 5000000 ; i++)
    {
        if(i == 1000018)
            k = i ;
        k = i ;
        n = 0 ;
        b[n] = 0 ;
        if(check[i] == 0)
        {
            ans[i] = i+1 ;
            continue ;
        }
        while(k != 1)
        {
            if(check[k] == 0 && k != a[n])
                    break;
            if(k % a[n] == 0)
            {
                k = k / a[n] ;
                b[n]++ ;

            }
            else
            {
                n++ ;
                b[n] = 0 ;
            }
        }
        if(k != 1)
        {
            ans[i] = k ;
            ans[i] = (ans[i]*ans[i]-1)/(ans[i]-1);
        }
        for(j = 0 ; j <= n ; j++)
        {
            if(b[j] != 0){
                __int64 kk = F(a[j],b[j]+1) - 1 ;
                ans[i] *= ( kk / (a[j]-1) );
            }
        }
    }
    for(i = 1 ; i <= 5000000 ; i++)
        ans[i] += ans[i-1];
    int l , r ;
    printf("%I64d\n", ans[5000000]);
    while(scanf("%d %d", &l, &r)!=EOF)
    {
        if(l == 0 && r == 0)
            break;
        if(l == 0)
            printf("%I64d\n", ans[r]);
        else
            printf("%I64d\n", ans[r] - ans[l-1]);
    }
    return  0;
}


为了计算个数n的所有非自身因子,可以采用以下几种方式之: 遍历查找法: 对于较小的数字,可以直接从1遍历至该数减(n-1),检查每个整数是否能被n整除。如果i (1 ≤ i < n) 能够整除n,则i是n的因子。 优化遍历查找法: 考虑到因子总是成对出现(除了完全平方数),即若a * b = n, 则当找到个小于根号下n的因子a时,另个大于根号下n的因子b也可以同时确定下来。所以只需要遍历到$\sqrt{n}$即可,并且每次发现因子(a,b)就将它们都加起来,但要注意排除掉n本身以及处理好完全平方的情况。 埃拉托斯特尼筛法变种: 预先构建个数组来存储每个索引对应的因子,然后利用类似埃拉托斯特尼筛选素数的方法更新这个数组中的值。这种方法适合批量求解多个不同数字的因子的问题。 具体实现代码如下所示: ```python import math def sum_of_divisors(n): # 如果n为1直接返回0因为1没有非自身的因数 if n == 1: return 0 result = 1 # 因子包括1但是不包括自己 sqrt_n = int(math.sqrt(n)) + 1 for i in range(2, sqrt_n): if n % i == 0: divisor_pair_sum = i other_divisor = n // i # 若不是完全平方数则加上另因子 if i != other_divisor: divisor_pair_sum += other_divisor result += divisor_pair_sum return result # 示例调用函数 print(sum_of_divisors(28)) ``` 这段Python代码实现了第二种方法——优化后的遍历查找法,用来找出给定整数`n`的所有小于其本身的因子
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值