JZOJ 1240. Fibonacci sequence
生活随笔
收集整理的這篇文章主要介紹了
JZOJ 1240. Fibonacci sequence
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原題
題解
對于80%的數據,根據遞推式用O(n)的方法就可以了。
對于100%的數據,顯然要用到矩陣方法,這里介紹兩種思路。
設 F(n),S(n) 分別為 Fibonacci?sequence 的第n項和前n項和。
求第x~y項的和相當于求 S(y)?S(x?1)。
于是問題變成了怎么求 S(y) 和 S(x?1)。
出 S(n) 的通項,和 F(n) 的通項比較。
可以發現 S(n)=F(n+2)?1,于是就用矩陣乘法求出數列的第 N+2 項。
但這樣的方法在比賽中不可取,因為,
f(n)=5√5[(1+5√2)n?(1?5√2)n]
S(n)=5√5[(1+5√2)n+2?(1?5√2)n+2]?1
顯然除非你的手算能力足夠強,否則這需要浪費大量時間才能推倒出來。
當然,由于 S(n)=F(n+2)?1 規律還是優美的。
善于觀察的同寫幾項出來就可以發現規律.
根據 f(n)=f(n?1)+f(n?2),S(n)=S(n?1)+f(n)
我們可以按如下方法構造一個矩陣。
[f(n)f(n?1)S(n)]=[f(n?1)f(n?2)S(n?1)]????110100111???
這種方法比較直觀,對矩陣乘法比較熟悉的同學應該很容易想到.
Code
#include<cstdio> #include<cstring> using namespace std; int mid[2][2],s[2][2],c[2]; int mid1[2][2],mid2[2][2]; int ans1[2],ans2[2]; const int mo=10000; inline int read() {int data=0; char ch=0;while(ch<'0' || ch>'9') ch=getchar();while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();return data; }//讀入優化 inline void ksm1(int v) {int ans[2][2];ans[0][0]=ans[1][1]=1;ans[1][0]=ans[0][1]=0;while(v){if(v%2){memset(s,0,sizeof(s));for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++)s[i][j]=(s[i][j]+ans[i][k]*mid1[k][j])%mo;memcpy(ans,s,sizeof(ans));}memset(s,0,sizeof(s));for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++)s[i][j]=(s[i][j]+mid1[i][k]*mid1[k][j])%mo;memcpy(mid1,s,sizeof(mid1));v/=2;}memcpy(mid1,ans,sizeof(mid1)); }//快速冪前x-1項 inline void ksm2(int v) {int ans[2][2];ans[0][0]=ans[1][1]=1;ans[1][0]=ans[0][1]=0;while(v){int s[2][2];if(v%2){memset(s,0,sizeof(s));for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++)s[i][j]=(s[i][j]+ans[i][k]*mid2[k][j])%mo;memcpy(ans,s,sizeof(ans));}memset(s,0,sizeof(s));for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++)s[i][j]=(s[i][j]+mid2[i][k]*mid2[k][j])%mo;memcpy(mid2,s,sizeof(mid2));v/=2;}memcpy(mid2,ans,sizeof(mid2)); }//快速冪前y項 int main() {mid[0][1]=mid[1][1]=mid[1][0]=1;int T=read();while(T--){int x=read(),y=read();ans1[0]=ans1[1]=ans2[0]=ans2[1]=1;memcpy(mid1,mid,sizeof(mid1));memcpy(mid2,mid,sizeof(mid2));ksm1(x-1);ksm2(y);memset(c,0,sizeof(c));for(int i=0;i<2;i++)for(int j=0;j<2;j++)c[i]=(c[i]+ans1[j]*mid1[i][j])%mo;memcpy(ans1,c,sizeof(ans1));memset(c,0,sizeof(c));for(int i=0;i<2;i++)for(int j=0;j<2;j++)c[i]=(c[i]+ans2[j]*mid2[i][j])%mo;//矩陣乘法memcpy(ans2,c,sizeof(ans2));printf("%d\n",(ans2[1]+mo-ans1[1])%mo);//相減得區間和}return 0; }總結
以上是生活随笔為你收集整理的JZOJ 1240. Fibonacci sequence的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 3453【NOIP2013中秋
- 下一篇: JZOJ 1422. 猴子摘桃