歡迎前往個人搭建部落格 five-great的部落格
description
求f12+f22+f32+…+fn2, 其中 fi 代表斐波那契數列的第 i 項。 (f0=0,f1=1)當然結果會很大,請將它對 109+7取模。
輸入格式
一行乙個數 n.
輸出格式
一行乙個數,代表答案。
樣例樣例輸入
樣例輸出 資料範圍與提示對於30%的資料:n≤105。
對於另外20%的資料: 1000000∣n (即n是1000000的倍數),且n≤5∗109。
對於100%的資料:n≤1018。
解體思路:首先需要搞清楚斐波那契數列求和蘊含的規律,先找到它的遞迴形式:
則其各項相加的平方和為:
以幾何的手段證明:12+12+22+32+52+82=8×13
設斐波那契數列的各項為正方形邊長,則所求平方和就是算正方形的面積,但是求冪運算需要迴圈逐個累乘,其複雜度為o(n),這在很多時候是不夠的,所以我們需要用快速冪——反覆平方法來加速冪運算的過程,要想辦法減少步驟,把其中的某一部分合成一步來進行。
比如,如果n能被2整除,那我們可以先計算一半,得到a^(n/2)的值,再把這個值平方得出結果。這樣做雖然有優化,但優化的程度很小,仍是線性的複雜度。
再比如,如果我們能找到2k = n,那我們就能把原來的運算優化成((((a2) 2) 2)…),只需要k次運算就可以完成,效率大大提公升。可惜的是,這種條件顯然太苛刻了,適用範圍很小。不過這給了我們一種思路,雖然我們很難找到2k == n,但我們能夠找到2k1 + 2k2 + 2k3 +…+ 2km =n。這樣,我們可以通過層層遞推,在很短的時間內求出各個項的值。可是又有新的問題出現了,我們並不清楚k1、k2…km具體的值是多少,對於不同的n,有不同分法,有沒有一種規則能把這些分法統一起來。
我們都學習過進製與進製的轉換,知道乙個b進製數的值可以表示為各個數字的值與權值之積的總和。比如,2進製數1001,它的值可以表示為10進製的123 + 022 + 021 + 120,即9。這完美地符合了上面的要求。可以通過2進製來把n轉化成2^km的序列之和,而2進製中第i位(從右邊開始計數,值為1或是0)則標記了對應的2(i - 1)是否存在於序列之中。譬如,13為二進位制的1101,他可以表示為23 + 22 + 20,其中由於第二位為0,21項被捨去。
如此一來,我們只需要計算a、a2、a4、a8…的值(這個序列中的項不一定都存在)並把它們乘起來即可完成整個冪運算。借助位運算的操作,可以很方便地實現這一演算法,其複雜度為o(logn)。
套用以下模板:
typedef
long
long ll;
ll quick_pow
(ll a, ll n)
//a^n
return re;
}
本題需要取模,直接在每一步運算中對a和re取模即可。
ac**:
#include
#include
#define ll long long
#define mod 1000000007
struct nobe
;ll n;
ll sum;
nobe mut
(nobe x,nobe y)
void
quick
(ll n)
printf
("%ld\n",(
(res.a[0]
[1]%mod)
*(res.a[0]
[1]%mod+res.a[1]
[1]%mod)
)%mod);}
intmain()
return0;
}
斐波那契(矩陣快速冪)
斐波那契數列,即fib n fib n 1 fib n 2 fib n fib n 1 fib n 2 fib n fib n 1 fi b n 2 就這麼乙個數列,顯然可以直接遞推求解,時間複雜度o n o n o n 似乎沒什麼問題。然後就遇到了這個,n nn的取值範圍最大是2 1 09 2 t...
快速冪 斐波那契數列
1 編寫程式,求解a b。其中b是正整數。方法1.一般求冪演算法,o r public static long power1 int a,int r if r 0 long res 1 for int i 1 i r i return res 這種使用連乘計算冪值的演算法,複雜度是o n 不過如果將...
矩陣快速冪 斐波那契數列
time limit 1000 ms memory limit 128 mb 通過小l的不懈努力,他即將成為大神啦,他登上了大神專屬的頒獎臺。在頒獎台上,他即將領取代表著大神的無限榮譽的勳章。小l走上頒獎台後,在台上發現了乙個製作精美的盒子。榮譽勳章就在盒子裡面。小l發現這個盒子被上了鎖,在這個盒子...