1. 程式人生 > >LightOJ - 1245 Harmonic Number (II) (找規律)

LightOJ - 1245 Harmonic Number (II) (找規律)

can 時間復雜度 += splay info code sqrt class .com

題目大意:給出一個n(1 <= n < 2^31)求出H(n)的結果,H(n)的定義為下:

技術分享圖片

分析:對於一個n,設 t = n / i:

  滿足 t >= 1的有多少個呢?  有 n / 1 個。

  滿足 t >= 2的有多少個呢?  有 n / 2 個。

  ……

  滿足 t >= k的有多少個呢?  有 n / k 個。

以上結論不難發現,我們再進一步就能發現:

  滿足 t == 1 的有 n/1 - n/2 個

  滿足 t == 2 的有 n/2 - n/3 個

  ……

  滿足 t == k 的有 n/k - n/(k+1) 個

發現這個規律,我們就需要考慮這個 t 枚舉到哪呢?t 從1 枚舉 到 n 肯定是對的,但是時間上不允許,我們可以改進一下,我們在枚舉 t >= i 的時候,我們可以順便計算出滿足 t >= n/i 的有多少個(舉個例子,n == 10,t >= 2的有5個,那麽t>=5的就有2個)。這樣一來時間復雜度就變為O(√n)了,這樣就足夠了。詳情見代碼:

技術分享圖片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <cmath>
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 typedef unsigned long long ULL;
 9 
10 LL H(int n){
11     LL ans = 0;
12     int m = sqrt(n+0.5);
13     for(int i = 2; i <= m; ++i){
14 ans += (LL)(i-1)*(n/(i-1)-n/i); 15 ans += n/(i-1); 16 } 17 ans += m*(n/m - m); 18 ans += n/m; 19 return ans; 20 } 21 22 int main(){ 23 int T, ca = 1; 24 scanf("%d", &T); 25 while(T--){ 26 int n; 27 scanf("%d", &n); 28 printf("
Case %d: %lld\n", ca++, H(n)); 29 } 30 return 0; 31 }
View Code

  

LightOJ - 1245 Harmonic Number (II) (找規律)