约数个数定理:
n可以分解质因数:n=p1^a1×p2^a2×p3^a3*…*pk^ak;
n的约数的个数是:(a1+1)(a2+1)(a3+1)…(ak+1);
约数和定理:
n的(a₁+1)(a₂+1)(a₃+1)…(ak+1)个正约数的和:
sum = (p1^0+p1^1+p1^2+…p1^a1)(p2^0+p2^1+p2^2+…p2^a2)…(pk^0+pk^1+pk^2+…pk^ak);
证明略(可以百度,也可自证,不难证)。
拓展:
问题:求【1, n】范围内,约数个数最大为多少(1<=n<=1e18);
分析:(感觉不对的话,欢迎留言)
由于约数个数的算法是乘积的关系,设为:
A1∗A2∗A3...An,(Ai=ai+1,ai是第i个因子的指数)
A
1
∗
A
2
∗
A
3...
A
n
,
(
A
i
=
a
i
+
1
,
a
i
是
第
i
个
因
子
的
指
数
)
;
如果i < j 且Ai < Aj,此时交换Ai和Aj的位置(不是单纯的交换位置,对应原因子的底数不同),结果肯定小于n满足条件,那么就存在某个因子的指数可以增加(小于n)。所以,
当i<j时Ai>=Aj;
当
i
<
j
时
A
i
>=
A
j
;
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
int p[20] = {0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51};
LL sum = 0;
inline void dfs(LL ans, LL n, LL cnt, int id, int time) {
if(p[id - 1] == 51) {
sum = max(sum, cnt);
return ;
}
if(ans > n / p[id]) {
sum = max(sum, cnt);
return ;
}
LL tt = 1;
for(int i = 0; i <= time; ++i) {
if(ans * tt > n) return;
dfs(ans * tt, n, cnt * (i + 1), id + 1, i);
if(tt > n / p[id]) return;
tt *= p[id];
}
}
int main() {
int T; LL n;
scanf("%d", &T);
while(T--) {
scanf("%lld", &n);
sum = 0;
dfs(1, n, 1, 1, 10);
printf("%lld\n", sum);
}
return 0;
}