MENU

求因子和

April 4, 2020 • 题解

Input

输入一个正整数T(T<=10000),表示有T组数据,每组数据包括一个整数n(1<=n<=1e12)

Output

输出这个数的因子和

Sample Input

1
2

Sample Output

3

解析:

利用唯一分解定理/算数基本定理来解决这道题

因为题目所给的数据十分bigou,所以利用暴力枚举的方式应该是不太现实的

那我们先来解释一下什么是唯一分解定理吧:

对于任何一个整数n,都可以将其拆分为:

$$ n = p_1^{\alpha1}p_2^{\alpha2}p_3^{\alpha3}…p_k^{\alpha k} 其中(p_i)是素数 $$

那么,n的因子个数=

$$ (a_1+1)(a_2+1)(a_3+1)……(a_k+1) $$

n的所有因子和=

$$ (1+p_1^1+p_1^2+p_1^3+…p_1^{a1})(1+p_2^1+p_2^2+p_2^3+…p_2^{a2})…(1+p_k^1+p_k^2+p_k^3+…p_k^{ak}) $$

我们可以利用等比数列求和公式来对式子化简:

$$ (1+p_1^1+p_1^2+p_1^3+…p_1^{a1})={p^{n+1}-1\over p-1} $$

有了这个公式,我们便可以开始写代码了:

#include <bits/stdc++.h>
using namespace std;
const long long MAX=1e6+3;
long long prime[MAX+10],cnt=0,number;
//学长说这里如果不写到1e6+3的话会卡数据999999999989
bool vis[MAX+10];
int getprime(){
    memset(vis,true,sizeof(vis));
    vis[0]=vis[1]=false;
    for (int i=2;i<=MAX;i++){
        if (vis[i])
            prime[++cnt]=i;
        for (int j=1;j<=cnt&&prime[j]*i<=MAX;j++){
            vis[prime[j]*i]=false;
            if (i%prime[j]==0) break;
        }
    }
    return 0;
}
//素数打表
long long sum(long long x){
    long long s=1;
    for (int i=1;prime[i]*prime[i]<=x;i++){
        if (x%prime[i]==0){
            //先找到x的素因子
            long long t=1;
            while (x%prime[i]==0)
                t*=prime[i],x/=prime[i];
            s*=(t*prime[i]-1)/(prime[i]-1);
        }
    }
    if (x>1) s*=(1+x);
    return s;
}
int main(){
    ios::sync_with_stdio(false);
    getprime();
    cin>>number;
    long long n;
    while (number--){
        cin>>n;
        printf("%lld\n",sum(n));
    }
    return 0;
}
作者:NorthCity1984
出处:https://grimoire.cn/acm/factor-sum.html
版权:本文《求因子和》版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

Last Modified: April 10, 2020