Your Name 题解
Problem
给定一个数 \(n\),求 \(1\) 到 \(n\) 的约数个数和。
Solution
\(\text{40pts}\):
使用一个 for
枚举 \(n\) 以内的数的所有约数,时间复杂度 \(O(n^2)\)。
点击查看代码
for(int i=1;i<=n;++i){
for(int j=1;j<=i;++j) if(i%j==0) ans++;
}
\(\text{70pts}\):
因为约数关于根号对称分布,所以可以根号枚举一个数的约数,时间复杂度 \(O(n\sqrt{n})\)。
点击查看代码
for(int i=1;i<=n;++i){
for(int j=1;j*j<=i;++j){
if(i%j==0&&j*j!=i) ans+=2;
if(j*j==i) ans++;
}
}
\(\text{100pts}\):
考虑将问题转化为 \([1,n]\) 区间内每一个数有多少个倍数 \(\leq n\)。
那么如何计算一个数 \(i\) 在 \(n\) 以内有多少个倍数呢?
设 \(n\) 以内为 \(i\) 的最大倍数的数为 \(i \times k\),也就是说,\(n\) 以内有 \(k\) 个 \(i\) 的倍数。
因为 \(k=i \times k \div i\),所以考虑求出 \(i \times k\)。
因为在 C++
语言中,整数除法是自动向下取整的,即小学数学中的“去尾”,所以在本题中,n/i
等同于 i*k/i
。一个 for
枚举即可,时间复杂度 \(O(n)\)。
点击查看代码
for(int i=1;i<=n;++i){
ans+=n/i;
}