题意:
定义 f(x) = { num | a*b| x } , 求 \sum { f(x) } , x <= 10^11
思路:
题目等价于求 a*b*c <= n 的数量.
假定 a <= b <= c. 则 a <= n^(1/3) , b <= n^(1/2)
所以我们可以通过枚举 a,b 计算出数量,时间复杂度未 O(n^(2/3))
对于枚举的 a, b, c; 有三种情况
1 . 三个相等 a, a, a 则只需要计算一次 ,
数量为: n^(1/3)
2. 二个相等, a, a, b or a, b, b 则需要计算 C(1,3) = 3 次
数量为: n/(a*a) - a and (n/a)^(1/2) - a
3. 三个都不相等 a, b, c , 则方案数为 P(3,3) = 6 次
数量为: n/(a*b) - b
另外要注意的是, 直接用pow(n,m) 求得的值会 四舍五入.要注意 保证 m*m <= n or m*m*m <= n 中最大的m
View Code
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> typedef long long LL; LL pow2(LL x){ LL m = pow(x,0.5); while(m*m<=x) m++; while(m*m>x) m--; return m; } LL pow3(LL x){ LL m = pow(x,1./3); while(m*m*m<=x) m++; while(m*m*m>x ) m--; return m; } int main(){ int Case = 1; LL n; while( scanf("%lld", &n) != EOF){ LL A = pow3(n), res = A; for(LL a = 1; a <= A; a++){ LL ni = n/a, k = pow2(ni); res += 1LL*( (ni/a-a) + (k-a) )*3; for(LL b = a+1; b <= k; b++){ res += 1LL*(ni/b-b)*6; } } printf("Case %d: %lld\n",Case++, res ); } return 0; }