LightOJ 1245 - Harmonic Number (II)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1245
题意:仿照上面那题他想求这么个公式的数。但是递归太慢啦。让你找公式咯。
题解:显然直接longlong存不下。暴力肯定不行啦。这题真的写了很久,死都不懂怎么找的公式啊。然后在wjd的帮助下懂了这题。
我们先列举几个例子
有没有发现他们的共同点,就是除到一定程度,就会变成1。这个临界点是sqrt(n)。那在sqrt(n)前面我们要算的就是这个数对于1,2,3……sqrt(n)的因子个数。
这个因子个数设为x。
n = i * x;
这个时候如果直接求是会TLE的。所以会推出来一个公式。
x = (n / i - n / (i+1) ) * i;
至于这个公式怎么出来的。网上有篇博客是画图推的。QWQ。
这个公式是求什么的呢?其实就是求 x为 1~sqrt(n) 的时候,会有几个这样的式子。
拿10举例,
x = 1 ,i = 6,7,8,9,10。 5个
x = 2 ,i = 4 , 5。 2个
x = 3 ,i = 3。 1个
i在1~sqrt(n)之间当然就可以直接求个数啦。 大胆的n/i。
把所有的x加起来就是答案。因为n可能为平方数,sqrt(n)可能多算了一次所以要减去这一次。
这个真的很难懂啊。QAQ、要多看几遍才行。
1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #define ll long long 5 using namespace std; 6 int main(){ 7 int T; 8 cin>>T; 9 int t = 1; 10 while(T--){ 11 int n; 12 cin>>n; 13 ll sum = 0; 14 int tot = sqrt(n); 15 for(int i = 1; i <= tot ;i++){ 16 sum += n / i; 17 } //枚举 sqrt(n) ~ n x在1~sqrt(n)直接算 18 for(int i = 1; i <= tot ;i++ ){ 19 sum += (n / i - n / (i+1)) * i; 20 } //枚举1~sqrt(n); x在后面就用公式 21 if( tot == n / tot ) 22 sum -= tot; 23 printf("Case %d: %lld\n",t,sum); 24 t++; 25 } 26 return 0; 27 }