1. 程式人生 > >1 股神

1 股神

urn 根據 ios ace fff 方便 es2017 回歸 -s

問題描述:

有股神嗎?

有,小賽就是!

經過嚴密的計算,小賽買了一支股票,他知道從他買股票的那天開始,股票會有以下變化:第一天不變,以後漲一天,跌一天,漲兩天,跌一天,漲三天,跌一天...依此類推。

為方便計算,假設每次漲和跌皆為1,股票初始單價也為1,請計算買股票的第n天每股股票值多少錢?

技術分享

解題思路:

找規律:設 f(n)為第 n 天的股票錢。 由題意知 f(1)=1 f(2)=2 f(3)=1 f(4) =2 f(5)=3 ... f(6)=2 ... f(10)=4 .... f(15)=7 ...f(21)=11 ...

標紅的是跌的那天股票錢。其實是有規律的。下面來找規律:

我們再定義 g(k)。g(1)=3, g(2)=6, g(3)=10,g(4)=15 ...

再定義u(m)。 u(1)=1, u(2)=2, u(3)=4,u(4)=7 ...

不難得出 g(k)=3+(k+4)*(k-1)/2 , u(m)=1+m*(m-1)/2 。

回歸到問題 現在給定 n ,求 f(n)。 我們如果 求出 n1 <= n <n2 其中 n1 和 n2是 n 中 相鄰兩次的下跌時天數。 即在 n1 至 n2 之間都是上漲的。

現在關鍵是求 n1 。 知道 n1 ,則 f(n)=f(n1)+n - n1。 現在問題轉為求 n1 和 f(n1)。

如果能得到 g(k)<= n < g(k+1) 則 n1 = g(k)。 因為 根據前面 g(k)的定義 g(k)就是 下跌時 對應的天數。

我們知道了 g(k)表達式 不難求出 k。 再回歸到 g(k)和 u(k)的定義(u(m)和u(k)意思一樣) , 有 f ( g(k) ) = u (k) 。

所以知道了k 就同時知道了 n1 和 f(n1) 。 問題解決。

現在為了盡量介紹 k 的叠代次數,用下面方法

(

   g(k)<= n =》 3+(k+4)*(k-1)/2 <= n =》 (k+4)*(k-1)/2 <= n =》 (k-1)*(k-1)/2 <= n =》 k<=sqrt(2*n)+1,

  如果 這是 k 的初始值的化 發現程序 輸入 n = 9 時 輸出 不正確。

  原因是, 這樣求出的 初始值K, 有 可能第一次帶入 g(k)就有 g(k)>n, 這樣是不行的 會出現這種情況 :

g(k)> g(k1) > n 。 跳 出 while 循環後 g(k)g(k2)> g(k1) > n (因為跳出循環前 執行了 k++ ) 所以當 k -= 2,其實 k = k1,

而我們以為 g(k1)< n 。 所以出現輸出錯誤。

出現這種情況的原因是 求 k的初始值時 當(k-1)*(k-1)/2 <= n 求出的k 有可能 (k-1)*(k-1)/2 <= n <(k+4)*(k-1)/2 。

如果我們能保證初始 的 k, 使得 (k+4)*(k-1)/2 < n 。就能避免上述的錯誤。

求(k+4)*(k-1)/2 <= n 我們求 (k+4)*(k+4)/2 <= n 的 k值 就能滿足 要求。

)

下面是代碼:

#include<iostream>
#include <cmath>
using namespace std;
int main(){
    int n;
    while(cin>>n){
        if(n<=0)
            continue;
        else if(n==1){
            cout<<1<<endl;
            continue;
        }
        int k=sqrtf(2*n)-4;  //為了減少叠代次數      
        if(k<0) k=0;
        int m=0;
        while(m<=n){
            m=3+(k+4)*(k-1)/2;
            k++;
        }
        k-=2;
        m=3+(k+4)*(k-1)/2;
        int i=1+k*(k-1)/2;
        i+=n-m;
        cout<<i<<endl;
    }
    return 0;
}

這種解法比較復雜 。網上有種 簡單的解法

代碼思路 如下:

public static int Cal2(int n){
        int i = 0;// i統計遇到了多少次下跌
        int j = 2;// 每次下跌之後上漲的天數,包含已經下跌的那天
        int k = n;
        while (k > j) {
            i += 2;
            k -= j;
            ++j;
        }
        return n - i;
    }

2017-09-14

1 股神