【LightOJ - 1098 】A New Function 【数论+思维】 1-n 每个数的因子的和

本文介绍了一种高效计算1到n所有整数的实际除数之和的方法(实际除数排除1和自身),通过数学推导简化了计算过程,实现了O(sqrt(n))的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

We all know that any integer number n is divisible by 1 and n. That is why these two numbers are not the actual divisors of any numbers. The function SOD(n) (sum of divisors) is defined as the summation of all the actual divisors of an integer number n. For example,

SOD(24) = 2+3+4+6+8+12 = 35.

The function CSOD(n) (cumulative SOD) of an integer n, is defined as below:

这里写图片描述
Given the value of n, your job is to find the value of CSOD(n).

Input
Input starts with an integer T (≤ 1000), denoting the number of test cases.

Each case contains an integer n (0 ≤ n ≤ 2 * 109).

Output
For each case, print the case number and the result. You may assume that each output will fit into a 64 bit signed integer.

Sample Input
3
2
100
200000000
Sample Output
Case 1: 0
Case 2: 3150
Case 3: 12898681201837053

题目是求1-n所有数字因子的和(因子不包括1和n这两个)。 这里我先求包括因子1和n的总和,这样结果肯定大了,但是最后减一下就好了(多余的部分也很好计算)。那怎么求我定义的这个呢?(假设我定义的最后结果为s(n))
S(n) = sigma( i : 1 - n ) ( floor( n / i ) * i )
然后再减去多计算的部分 就好了。
你可能无法理解这个公式 之前做过一个更简单的题目这里面的A题
懂了上面的公式之后。
我们发现时间复杂度还是不够啊,必须要化简为o(sqrt(n))的好像才可以过。
这就体现到了 数学题目中,缩小时间复杂度常用的手段: 从结果考虑,从可能产生的结果来考虑 什么样的情况会导致这个结果 。

(描述的不是很清楚,大家可以自己找规律来理解)
代码

#include<bits/stdc++.h>
using namespace std;
#define LL long long

const int N = (int)1e8+2;
const int M = 1E6+11;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

LL n;
LL get(LL x){ //对于每个可能的结果,1-n的一定会有一段区间的数字 会导致这样的结果
    LL a=n/x;
    LL b=n/(x+1)+1;
    return (a+b)*(a-b+1)/2*x;
}

int main(){
    int cas=1;
    int T;scanf("%d",&T);
    while(T--){
        scanf("%lld",&n);
        LL ans=0;
        for(LL i=1;i*i<=n;i++){
            LL a=i;
            LL b=n/a;  // a 和 b 就是 公式中 floor(n/i) 所有的可能结果之一 (之所以这样遍历得到,是因为我找了好几组数据 试了一下找到了规律)
            ans+=get(a);
            if(b!=a) ans+=get(b);
        }
        ans-=n+(2+n)*(n-2+1)/2;// 减去多计算的部分
        if(n==0) ans=0;
        printf("Case %d: %lld\n",cas++,ans);
    }
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值