一个数的约数和,约数个数问题

这篇博客介绍了如何使用线性筛法高效地计算一个数的约数个数和约数和。通过初始化素数表、判断素数、更新约数信息,实现了从1到n范围内每个数的约数个数和约数和的计算。代码中包含了三个不同的实现:计算约数个数、计算约数和以及求1~x中每个数的约数和的总和。
摘要由CSDN通过智能技术生成

一个数的约数个数

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
#define speed(x) ios::sync_with_stdio(false), cin.tie(x), cout.tie(x)
#define bug(x) cout << #x << " == " << x << '\n'
const ll MAX_N =1e6+10;
int tot=0;
ll prime[MAX_N] = { 0 };///范围n里面的素数
bool isp[MAX_N] = {0};///是不是为素数
int d[MAX_N] = { 0 };///约数数量
int num[MAX_N] = { 0 };///最小素数因子个数数量

inline void init(int n)///线性筛求约数个数
{
    d[1] = 1;
    for(int i=2;i<=n;i++)
    {
        if(!isp[i])///是素数的话
        {
            d[i]=2;///约数数量
            num[i]=1;///他自己就是最小素数因子
            tot++;
            prime[tot]=i;
        }
        for(int j=1;j<=tot && prime[j]*i<=n;j++)///不加后面那个条件可能会越界 我已经体会到了QwQ
        {
            isp[prime[j]*i] = 1;
            if(i%prime[j]==0)///prime[j]是i的最小素因子
            {

                num[i*prime[j]]=num[i]+1;
                d[i*prime[j]]=d[i]/( num[i]+1 )*(num[ i*prime[j] ]+1);
                ///约数数量为(每一位素因子的个数+1)相乘
                ///e.g:interage=p1^a1*p2^a2......pn^an.d[interage]=(1+a1)*(1+a2)....(an+1)
                ///而i*prime[j]与i的区别只是增加了一个最小素因子
                ///因此d[i*prime[j]]=d[i]/( num[i]+1 )*( num[i]+1+1)
                break;
            }
            d[ i*prime[j] ]=d[i]*2;///最小素因子的值改变,而且a1=1,a1+1=2,所以×2就好
            num[ i*prime[j] ]=1;///i*prime[j]目前最小素因子为prime[j]
        }
    }
}

int main()
{
    ll n;
    scanf("%lld",&n);
    init(n);
    for(int i=1; i<=n; i++)
    {
        printf("%lld ",d[i]);
    }
}

一个数的约数和

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
#define speed(x) ios::sync_with_stdio(false), cin.tie(x), cout.tie(x)
#define bug(x) cout << #x << " == " << x << '\n'
const ll MAX_N =1e6+10;
int tot=0;
ll prime[MAX_N] = { 0 };///范围n里面的素数
bool isp[MAX_N] = {0};///是不是为素数
ll sd[MAX_N] = {0};///约数和
ll sp[MAX_N] = {0};///最小素因子等比数列的和1+p1^1+p1^2+...+p1^a1
inline void init(ll n)///线性筛求约数个数
{
    sd[1] = 1;
    for(ll i=2; i<=n; i++)
    {
        if(!isp[i])///是素数的话
        {
            sd[i]=i+1;
            sp[i]=1+i;
            tot++;
            prime[tot]=i;
        }
        for(int j=1; j<=tot&&prime[j]*i<=n; j++)
        {
            isp[prime[j]*i] = 1;
            if(i%prime[j]==0)///prime[j]是i的最小素因子
            {
                 sp[ i*prime[j] ] = sp[i]*prime[j]+1;
                sd[i*prime[j]] = (sd[i]/sp[i]) * sp[ i*prime[j] ];
                ///i*prime[j]的最小素因子的等比数列为1+p1^1+p1^2+...+p1^(a1+1)=p1(1+p1^1+...+p1^a1)+1
                break;
            }
            sd[ i*prime[j] ] = sd[i]*sd[ prime[j] ];
            sp[ i*prime[j] ] = sp[ prime[j] ];
        }
    }
}
int main()
{
    ll n;
    scanf("%lld",&n);
    init(n);
    for(int i=1; i<=n; i++)
    {
        printf("%lld\n",sd[i]);
        ///o[i] = o[i-1] + sd[i];
        ///printf("%lld ",(ll)i*n-o[i]);
    }
}

1~x中 每一个数的约数和 的和(利用除法分块写)

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
#define speed(x) ios::sync_with_stdio(false), cin.tie(x), cout.tie(x)
#define bug(x) cout << #x << " == " << x << '\n'
const ll MAX_N =1e6+10;

ll solve(ll n)
{
    ll ans=0;
    ll r=1;
    for(ll l=1;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans += (n/l) * (l+r)*(r-l+1)/2;
    }
    return ans;
}
int main()
{
    ll x;
    scanf("%lld %lld",&x);
  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值