zoj 3175 Number of Containers

/*
* zoj3175.c
*
* Created on: 2011-9-20
* Author: bjfuwangzhu
*/
/*
题目描述:给定一个n,求1,2。。。n所有数的约数个数和f(n)
例如f(5)=10-5,f(4)=8-4
由于这个n非常大,故有两种思考方向,第一种是找该函数的递推或者公式,貌似很难而且每有头绪
还有种思考的方式就是我们按段来统计,就是统计区间上有多少个数含有这个约数,我们是可以O(1)时间计算的
接下来就是如何分这个段,其实这个问题反映到坐标系中就是对于x*y<=n,我们要找在这个图形中所有的正整数点
我们用直线x=y把这个图形分成两部分,显然这两部分是对称的,于是我们可以令i=[1,sqrt(n)] 累加n/i (其实就是我之前说的段)
这个再*2,但是注意到对角线上的元素我们计算了两次,故要减去k*k(k=sqrt(n))
为什么是这个我们把整点看成基点,就是说面积通过数基点得到,我们对应到坐标上是双曲线,发现每次重算的部分叠加起来正好是一个正方形
内所有的整点,故是k*k
*/

#include
<stdio.h>
#include
<math.h>
typedef
long long LL;
int main() {
#ifndef ONLINE_JUDGE
freopen(
"data.in", "r", stdin);
#endif
int T, i, te, n;
LL res;
while (~scanf("%d", &T)) {
while (T--) {
scanf(
"%d", &n);
te
= (int) sqrt(n * 1.0);
for (i = 1, res = 0; i <= te; i++) {
res
+= n / i;
}
res
= (res << 1) - te * te;
res
-= n;
printf(
"%lld\n", res);
}
}
return 0;
}

原文地址:https://www.cnblogs.com/xiaoxian1369/p/2182787.html