数论(约数之和) - Sigma Function - LightOJ 1336
题意:
根 据 算 数 基 本 定 理 , 对 任 意 正 整 数 n , 可 分 解 为 : 根据算数基本定理,对任意正整数n,可分解为: 根据算数基本定理,对任意正整数n,可分解为:
n = p 1 a 1 × p 2 a 2 × . . . × p k a k , 其 中 p 1 , p 2 , . . . , p k 是 n 的 素 因 子 , a i ≥ 0 。 n=p_1^{a_1}×p_2^{a_2}×...×p_k^{a_k},其中p_1,p_2,...,p_k是n的素因子,a_i≥0。 n=p1a1×p2a2×...×pkak,其中p1,p2,...,pk是n的素因子,ai≥0。
约 数 之 和 : 约数之和: 约数之和:
σ ( n ) = p 1 a 1 + 1 − 1 p 1 − 1 × p 2 a 2 + 1 − 1 p 2 − 1 × . . . × p k a k + 1 − 1 p k − 1 σ(n)=\frac{p_1^{a_1+1}-1}{p_1-1}×\frac{p_2^{a_2+1}-1}{p_2-1}×...×\frac{p_k^{a_k+1}-1}{p_k-1} σ(n)=p1−1p1a1+1−1×p2−1p2a2+1−1×...×pk−1pkak+1−1
= ( 1 + p 1 1 + p 1 2 + . . . + p 1 a 1 ) × ( 1 + p 2 1 + p 2 2 + . . . + p 2 a 2 ) × . . . × ( 1 + p k 1 + p k 2 + . . . + p k a k ) =(1+p_1^1+p_1^2+...+p_1^{a_1})×(1+p_2^1+p_2^2+...+p_2^{a_2})×...×(1+p_k^1+p_k^2+...+p_k^{a_k}) =(1+p11+p12+...+p1a1)×(1+p21+p22+...+p2a2)×...×(1+pk1+pk2+...+pkak)
计 算 区 间 [ 1 , n ] 内 , 有 多 少 个 正 整 数 i , 满 足 i 的 约 数 之 和 σ ( i ) 是 偶 数 。 计算区间[1,n]内,有多少个正整数i,满足i的约数之和σ(i)是偶数。 计算区间[1,n]内,有多少个正整数i,满足i的约数之和σ(i)是偶数。
输入:
T 组 测 试 数 据 , T组测试数据, T组测试数据,
每 组 包 括 一 个 正 整 数 n 。 每组包括一个正整数n。 每组包括一个正整数n。
输出:
一 个 正 整 数 , 表 示 答 案 。 一个正整数,表示答案。 一个正整数,表示答案。
Sample Input
4
3
10
100
1000
Sample Output
Case 1: 1
Case 2: 5
Case 3: 83
Case 4: 947
数据范围:
T ≤ 100 , 1 ≤ n ≤ 1 0 12 T≤100,1≤n≤10^{12} T≤100,1≤n≤1012
分析:
对 于 每 个 正 整 数 n , 求 约 数 之 和 的 时 间 复 杂 度 为 O ( n ) , 对于每个正整数n,求约数之和的时间复杂度为O(\sqrt{n}), 对于每个正整数n,求约数之和的时间复杂度为O(n),
若 对 [ 1 , n ] 内 的 每 个 数 都 暴 力 统 计 一 次 , 显 然 是 不 能 够 的 。 若对[1,n]内的每个数都暴力统计一次,显然是不能够的。 若对[1,n]内的每个数都暴力统计一次,显然是不能够的。
我 们 考 虑 从 σ ( n ) 的 特 征 入 手 。 我们考虑从σ(n)的特征入手。 我们考虑从σ(n)的特征入手。
σ ( n ) 是 乘 积 的 形 式 , 我 们 要 判 断 其 奇 偶 性 , 我 们 知 道 : \sigma(n)是乘积的形式,我们要判断其奇偶性,我们知道: σ(n)是乘积的形式,我们要判断其奇偶性,我们知道:
① 、 偶 数 × 偶 数 = 偶 数 ①、偶数×偶数=偶数 ①、偶数×偶数=偶数
② 、 偶 数 × 奇 数 = 偶 数 ②、偶数×奇数=偶数 ②、偶数×奇数=偶数
③ 、 奇 数 × 奇 数 = 奇 数 ③、奇数×奇数=奇数 ③、奇数×奇数=奇数
由 此 可 见 , σ ( n ) 为 奇 数 的 可 能 性 是 比 较 少 的 。 由此可见,\sigma(n)为奇数的可能性是比较少的。 由此可见,σ(n)为奇数的可能性是比较少的。
所 以 , 我 们 可 以 求 出 [ 1 , n ] 内 , 约 数 之 和 为 奇 数 的 数 的 个 数 c n t , 再 用 总 数 n − c n t , 得 到 答 案 。 所以,我们可以求出[1,n]内,约数之和为奇数的数的个数cnt,再用总数n-cnt,得到答案。 所以,我们可以求出[1,n]内,约数之和为奇数的数的个数cnt,再用总数n−cnt,得到答案。
下探究σ(n)何时为奇数:
需 满 足 对 n 的 任 意 质 因 子 p i , 1 + p i 1 + p i 2 + . . . + p i a i 为 奇 数 。 需满足对n的任意质因子p_i,1+p_i^1+p_i^2+...+p_i^{a_i}为奇数。 需满足对n的任意质因子pi,1+pi1+pi2+...+piai为奇数。
在 所 有 的 素 数 中 , 仅 2 为 偶 数 , 其 他 素 数 均 为 奇 数 。 在所有的素数中,仅2为偶数,其他素数均为奇数。 在所有的素数中,仅2为偶数,其他素数均为奇数。
① 、 当 n 有 素 因 子 2 时 , 1 + 2 1 + 2 2 + . . . + 2 a 1 恒 为 奇 数 。 ①、当n有素因子2时,1+2^1+2^2+...+2^{a_1}恒为奇数。 ①、当n有素因子2时,1+21+22+...+2a1恒为奇数。
② 、 对 于 其 他 素 因 子 p i , 要 使 1 + p i 1 + p i 2 + . . . + p i a i 为 奇 数 , 必 有 p i 1 + p i 2 + . . . + p i a i 为 偶 数 , ②、对于其他素因子p_i,要使1+p_i^1+p_i^2+...+p_i^{a_i}为奇数,必有p_i^1+p_i^2+...+p_i^{a_i}为偶数, ②、对于其他素因子pi,要使1+pi1+pi2+...+piai为奇数,必有pi1+pi2+...+piai为偶数,
首 先 p i k 必 为 奇 数 , 偶 数 个 奇 数 相 加 为 偶 数 , 故 a i 必 为 偶 数 。 \qquad首先p_i^k必为奇数,偶数个奇数相加为偶数,故a_i必为偶数。 首先pik必为奇数,偶数个奇数相加为偶数,故ai必为偶数。
也 就 是 说 , 对 于 任 意 的 p i ≠ 2 , 1 + p i 1 + p i 2 + . . . + p i a i 为 奇 数 当 且 仅 当 a i 为 偶 数 。 \qquad也就是说,对于任意的p_i≠2,1+p_i^1+p_i^2+...+p_i^{a_i}为奇数当且仅当a_i为偶数。 也就是说,对于任意的pi=2,1+pi1+pi2+...+piai为奇数当且仅当ai为偶数。
总 结 : σ ( n ) 为 奇 数 , 当 且 仅 当 n 的 所 有 素 因 子 ( 除 了 2 以 外 ) 的 指 数 a i 均 为 偶 数 , 总结:\sigma(n)为奇数,当且仅当n的所有素因子(除了2以外)的指数a_i均为偶数, 总结:σ(n)为奇数,当且仅当n的所有素因子(除了2以外)的指数ai均为偶数,
若 存 在 素 因 子 2 , 对 因 子 2 的 指 数 无 要 求 。 \qquad\quad若存在素因子2,对因子2的指数无要求。 若存在素因子2,对因子2的指数无要求。
由 于 a i 为 偶 数 , 我 们 记 a i = 2 a i ′ , 则 n = 2 k × ( p 1 a 1 ′ ) 2 × ( p 2 a 2 ′ ) 2 × . . . × ( p k a k ′ ) 2 由于a_i为偶数,我们记a_i=2a_i',则n=2^k×(p_1^{a_1'})^2×(p_2^{a_2'})^2×...×(p_k^{a_k'})^2 由于ai为偶数,我们记ai=2ai′,则n=2k×(p1a1′)2×(p2a2′)2×...×(pkak′)2
其 中 k 为 任 意 非 负 整 数 , 我 们 发 现 , ( p 1 a 1 ′ ) 2 × ( p 2 a 2 ′ ) 2 × . . . × ( p k a k ′ ) 2 是 一 个 完 全 平 方 数 , 其中k为任意非负整数,我们发现,(p_1^{a_1'})^2×(p_2^{a_2'})^2×...×(p_k^{a_k'})^2是一个完全平方数, 其中k为任意非负整数,我们发现,(p1a1′)2×(p2a2′)2×...×(pkak′)2是一个完全平方数,
当 k 为 偶 数 时 , n 就 是 一 个 完 全 平 方 数 ; 当 k 为 奇 数 时 , n 是 一 个 完 全 平 方 数 的 两 倍 。 当k为偶数时,n就是一个完全平方数;当k为奇数时,n是一个完全平方数的两倍。 当k为偶数时,n就是一个完全平方数;当k为奇数时,n是一个完全平方数的两倍。
综 上 : σ ( n ) 为 奇 数 , 当 且 仅 当 n 是 一 个 完 全 平 方 数 或 是 一 个 完 全 平 方 数 的 两 倍 。 综上:\sigma(n)为奇数,当且仅当n是一个完全平方数或是一个完全平方数的两倍。 综上:σ(n)为奇数,当且仅当n是一个完全平方数或是一个完全平方数的两倍。
因 此 , 我 们 仅 需 统 计 出 [ 1 , n ] 以 内 , 所 有 是 完 全 平 方 数 和 完 全 平 方 数 的 2 倍 的 数 的 个 数 , 即 为 c n t 。 答 案 为 n − c n t 。 因此,我们仅需统计出[1,n]以内,所有是完全平方数和完全平方数的2倍的数的个数,即为cnt。答案为n-cnt。 因此,我们仅需统计出[1,n]以内,所有是完全平方数和完全平方数的2倍的数的个数,即为cnt。答案为n−cnt。
可 以 证 明 , 一 个 完 全 平 方 数 的 2 倍 一 定 不 是 完 全 平 方 数 , 因 此 统 计 这 两 种 数 不 会 产 生 冲 突 。 这 里 可 以 简 化 代 码 。 可以证明,一个完全平方数的2倍一定不是完全平方数,因此统计这两种数不会产生冲突。这里可以简化代码。 可以证明,一个完全平方数的2倍一定不是完全平方数,因此统计这两种数不会产生冲突。这里可以简化代码。
注意: 我 们 最 后 要 输 出 n − c n t , n 是 l o n g l o n g 级 别 的 , 最 后 要 以 长 整 型 格 式 输 出 。 我们最后要输出n-cnt,n是long\ long级别的,最后要以长整型格式输出。 我们最后要输出n−cnt,n是long long级别的,最后要以长整型格式输出。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int T;
ll n;
int main()
{
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>n;
int cnt=0;
for(ll i=1;i*i<=n;i++,cnt++)
if(2*i*i<=n) cnt++;
printf("Case %d: %lld\n",t,n-cnt);
}
return 0;
}