日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JZOJ 1240. Fibonacci sequence

發布時間:2025/3/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)=55[(1+52)n?(1?52)n]

    • S(n)=55[(1+52)n+2?(1?52)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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。