原題出自ural 1133。
題目大意:擴充套件斐波那契數列在整數集上的定義,即不是從f0
=0,f1=
1 這樣子開始的,下標可以是任意整數。給定這樣乙個序列中的兩個下標,i,j,以及他們在序列中對應的值fi
,fj ,然後要求fn
(n是輸入的乙個數字)。
思路1:由於題目裡說到資料範圍在 −2
∗109≤
fk≤2
∗109(
k=mi
n(i,
j,n)
,…,m
ax(i
,j,n
)).
所以可以考慮直接二分查詢fi
+1(在下面有分析)就好了(很容易驗證這個序列的單調性)。
思路2:觀察係數規律,i,j,n中的最小者是i,那麼: fi
+2=f
i+1+
fi, fi
+3=f
i+2+
fi+1
=2fi
+1+f
i , fi
+4=f
i+3+
fi+2
=3fi
+1+2
fi, … f
i+n=
fnfi
+1+f
n−1f
i . 其中f
n 是常規的斐波那契數列:,這個規律我稱之為「係數規律」。
現在只看i和j,假設j比i大,那麼: fi
,fi+
1,fi
+2,.
..,f
j ,有了「係數規律」,只需要求解fi
+1就好了,一旦知道了fi
+1,那麼就可以直接算出fn
了。怎麼算出n呢?假設n比i大,那麼根據上面推導的「係數規律」,有: fn
=fi+
(n−i
)=fn
−ifi
+1+f
n−i−
1fi.
所以關鍵是求出fi
+1,那麼怎麼求呢?還是根據「係數規律」!!!我們已知fi
和fj ,那麼就有: fj
=fi+
(j−i
)=fj
−ifi
+1+f
j−i−
1fi.
(1)
注意到方程(1)只有乙個未知數fi
+1,很容易求出: fi
+1=(
fi−f
j−i−
1fi)
/fj−
i.至此,貌似一切問題都解決了,不過還有兩個小問題:
1)如果n比i小?(反過來推就好了,知道fi
和fi+
1 之後)
2)需要預處理先求出斐波那契,但是這道題最多要計算到
f2000
,不會爆嗎?試試c++的long double咯,反正我過了,或者任性的,可以直接用python╮(╯▽╰)╭。
貼**如下:
#include
using
namespace
std;
typedef
long
double ld;
const
int max = 2005;
ld f[max];
int main()
// 因為陣列的下標應該是非負的
i += 1000, j += 1000, n += 1000;
// 求出f(i+1)
fii = (j - i == 1) ? fj : ((fj - f[j-i-1]*fi) / f[j-i]);
if (n == i)
fn = fi;
else
if (n - i == 1)
fn = fii;
else
if (n - i > 1)
}else
}cout
<< (int)fn << endl;
return
0;}
執行結果是:
好吧,雖然有點醜,但我覺得還是把演算法說到位了。
最後再說一句,這道題這麼敏感的計算,再次演示了「編譯器有毒」系列作品,用visual c++ 2013的人目測都會死得很慘,因為我就是用它,然後一直wa 10了,改用g++ 4.9就好了╮(╯▽╰)╭。。。。。
最後再貼我用python 3的**(矩陣快速冪+二分):
# ural 1133
unit = [[1, 1], [1, 0]]
defmul
(a, b):
ans = [[0
for i in range(0, len(a))] for j in range(0, len(b))]
for i in range(0, len(a)):
for j in range(0, len(b)):
for k in range(0, len(b)):
ans[i][j] += a[i][k] * b[k][j]
return ans
defpow
(n):
'''注意不能寫n /= 2,會被python當做浮點數,應該是用位運算'''
a = unit
b = [[1, 0], [0, 1]]
while n > 0:
if n & 1:
b = mul(a, b)
a = mul(a, a)
n >>= 1
return b
defcal
(i, fi, j, fj, n):
mat = pow(j-1)
[left, right] = [int(-2*1e9), int(2*1e9)]
while left <= right:
mid = (left + right) >> 1
x = mat[0][0] * mid + mat[0][1] * fi
if x > fj:
right = mid - 1
elif x < fj:
left = mid + 1
else:
break
if n > 0:
mat = pow(n - 1)
print(mid*mat[0][0] + fi*mat[0][1])
else:
[fa, fb] = [mid, fi]
for i in range(n, 0):
[fa, fb] = [fb, fa - fb]
print(fb)
if __name__ == '__main__':
[i, fi, j, fj, n] = [int(i) for i in input().split(' ')]
if i > j:
[i, j] = [j, i]
[fi, fj] = [fj, fi]
j -= i
n -= i
i = 0
cal(i, fi, j, fj, n)
斐波那契數列 斐波那契數列python實現
斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...
迴圈斐波那契數列 斐波那契數列應用
什麼是斐波那契數列 斐波那契數列指的是這樣乙個數列 1,1,2,3,5,8,13,21,34,55,89,144 這個數列從第3項開始,每一項都等於前兩項之和 台階問題 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...
斐波那契數列
1 題目描述 大家都知道斐波那契數列,現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項。斐波那契數列的定義如下 輸入 輸入可能包含多個測試樣例,對於每個測試案例,輸入包括乙個整數n 1 n 70 輸出 對應每個測試案例,輸出第n項斐波那契數列的值。2 這是九度上的乙個題,要求時間限制1秒,整數的...