约数个数和,约数之和,约数

约数定义

约数:约数,又称因数。整数a除以整数b(b≠0) 除得的商正好是整数而没有余数

1.求n的约数

vector<ll> get_divisors(ll n){//试除法求n的所有约数
    vector<ll> ans;
    for (ll i = 1; i <= n / i; i++) {
        if (n % i == 0) {
            ans.push_back(i);
            if (i != n / i) ans.push_back(n / i);
        }
    }
    //sort(ans.begin(), ans.end());
    return ans;
}

2.求n的约数个数

d i d_i di 表示 i i i 的约数个数, n u m i num_i numi 表示 i i i 的最小质因子出现次数。
定理:若 n = ∏ i = 1 m p i c i n=\prod_{i=1}^mp_i^{c_i} n=i=1mpici d i = ∏ i = 1 m c i + 1 d_i=\prod_{i=1}^mc_i+1 di=i=1mci+1.

证明:我们知道 p i c i p_i^{c_i} pici 的约数有 p i 0 , p i 1 , … , p i c i p_i^0,p_i^1,\dots ,p_i^{c_i} pi0,pi1,,pici c i + 1 c_i+1 ci+1 个,根据乘法原理, n n n 的约数个数就是 ∏ i = 1 m c i + 1 \prod_{i=1}^mc_i+1 i=1mci+1.
代码一:线性筛

void pre() {
  d[1] = 1;
  for (int i = 2; i <= n; ++i) {
    if (!v[i]) v[i] = 1, p[++tot] = i, d[i] = 2, num[i] = 1;
    for (int j = 1; j <= tot && i <= n / p[j]; ++j) {
      v[p[j] * i] = 1;
      if (i % p[j] == 0) {
        num[i * p[j]] = num[i] + 1;
        d[i * p[j]] = d[i] / num[i * p[j]] * (num[i * p[j]] + 1);
        break;
      } else {
        num[i * p[j]] = 1;
        d[i * p[j]] = d[i] * 2;
      }
    }
  }
}

代码二:

ll getnum(ll n){ //计算n的约数个数
    ll ans = 1;
    for (ll i = 2; i <= n / i; i++) {
        ll k = 0;
        while (n % i == 0) {
            n = n / i;
            k++;
        }
        if (k) ans *= (k + 1);
    }
    if (n != 1) ans = ans * 2;
    if (ans == 1) {
        if (n == 1) return 1;
        else return 2;
    }
    return ans;
}

3.求n的约数之和

f i f_i fi 表示 i i i 的约数和, g i g_i gi 表示 i i i 的最小质因子的 p + p 1 + p 2 + … p k p+p^1+p^2+\dots p^k p+p1+p2+pk.
代码一:线性筛

void pre() {
  g[1] = f[1] = 1;
  for (int i = 2; i <= n; ++i) {
    if (!v[i]) v[i] = 1, p[++tot] = i, g[i] = i + 1, f[i] = i + 1;
    for (int j = 1; j <= tot && i <= n / p[j]; ++j) {
      v[p[j] * i] = 1;
      if (i % p[j] == 0) {
        g[i * p[j]] = g[i] * p[j] + 1;
        f[i * p[j]] = f[i] / g[i] * g[i * p[j]];
        break;
      } else {
        f[i * p[j]] = f[i] * f[p[j]];
        g[i * p[j]] = 1 + p[j];
      }
    }
  }
  for (int i = 1; i <= n; ++i) f[i] = (f[i - 1] + f[i]) % Mod;
}

代码二:

ll qpow(ll a, ll b) {
    ll ans = 1;
    while (b) {
        if (b & 1)ans *= a;
        a *= a;
        b >>= 1;
    }
    return ans;
}
ll getsum(ll n) {//计算n的约数和是多少.
    ll ans = 1;
    for (ll i = 2; i <= n / i; i++) {
        ll t = 0;
        while (n % i == 0) {
            n = n / i;
            t++;
        }
        ans *= ((1 - qpow(i, t + 1)) / (1 - i));
    }
    if (n != 1) ans *= (1 + n);
    return ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值