1. 程式人生 > >HDU-problem-1002-人類史上最大最好的希望事件-矩陣快速冪

HDU-problem-1002-人類史上最大最好的希望事件-矩陣快速冪

i++ 常常 星空 ont con struct urn \n 矩陣快速冪

Problem Description

作為CNCS的半壁江山,狗哥常常在宇宙中心邵陽眺望黃浦江,夜晚的星空總是迷人,有時候還能見到彗星滑落。

狗哥是幸運的,他在兩秒鐘內看到了十七顆彗星劃過天際,作為打ACM的學者,自然不會有「穩定-1」情況。他開始研究彗星運動的軌跡,發現他們都遵照斐波那契螺旋線在運動著。

尤裏卡!狗哥覺得這就是找尋「生命,宇宙和一切的終極答案」的精要所在,但是怎麽表示呢?狗哥覺得求取斐波那契螺旋線經過的一個個方格的面積之和就是公式的表現。

例如下圖,螺旋線每劃過一個方格,都轉過了四分之一圈。如果我們以四分之一圈為單位,那麽我們用類似帶分數的形式表示螺旋線轉動的起點和終點。例如,0+0 到 0 + 1 意即從第一個方格轉到第二個方格,劃過了前兩個方格,他們的面積之和為2(1+1)。同理,0+0 到 1+0 劃過了前五個方格,他們的面積之和為40(1+1+4+9+25)。

技術分享圖片


但是聰明的狗哥需要一個程序去獲得指定範圍內的螺旋線面積之和,狗哥給了你一首「希望之花」的時間,而他需要利用這個時間去打出四暗刻單騎。如果你能完成這個程序,狗哥會封你為格拉摩根伯爵

Input 不定組數據。

首先輸入一個整數Q,代表狗哥詢問次數。

接下來Q行,每行四個整數a,b,c,d,代表狗哥想求 a+b 到 c+d 之間的螺旋線面積之和。

1<= Q <= 10000

0<= a,c <= 10000

0 <= b,d <= 3

結果對192600817取模。

Output 一個數字,表示螺旋線面積之和。

Sample Input 4 0 0 0 1 0 0 1 0 1 2 2 1 1 1 0 3 4 0 0 0 1 0 0 1 0 1 2 2 1 1 1 0 3

Sample Output 2 40 4791 98 2 40 4791 98 題意: 求"a+b"到"c+d"以斐波那契數列為邊長的正方形的面積之和,其中a或c是只有多少個4個正方形,b或d表示有b+1或d+1個正方形.如0+0是第一個正方形,0+1是第二個正方形,1+0是第五正方形. 簡單的說就是"0+0","0+1","0+2","0+3","1+0"...的正方形. 註意:打表時需要每次都將矩陣初始化,否則上一次計算的結果會保留到下一次導致計算錯誤.
 1 #include<iostream>
 2 #include<cstdio>
 3
#include<cstring> 4 #define ll long long 5 using namespace std; 6 ll an[30005]; 7 const ll mod=192600817; 8 struct Mat 9 { 10 ll m[2][2]; 11 } ans,A;; 12 Mat mul(Mat A,Mat B) 13 { 14 Mat ret; 15 for(int i=0; i<2; i++) 16 for(int j=0; j<2; j++) 17 { 18 ret.m[i][j]=0; 19 for(int k=0; k<2; k++) 20 ret.m[i][j]=(ret.m[i][j]+((A.m[i][k])*(B.m[k][j]))%mod)%mod; 21 } 22 return ret; 23 } 24 Mat pow(Mat A,long long n) 25 { 26 Mat ret; 27 ret.m[0][0]=1; 28 ret.m[0][1]=0; 29 ret.m[1][0]=0; 30 ret.m[1][1]=1; 31 while(n) 32 { 33 if(n&1) 34 ret=mul(ret,A); 35 A=mul(A,A); 36 n>>=1; 37 } 38 return ret; 39 } 40 void init() 41 { 42 ans.m[0][0]=1; 43 ans.m[0][1]=0; 44 A.m[0][0]=1; 45 A.m[0][1]=1; 46 A.m[1][0]=1; 47 A.m[1][1]=0; 48 } 49 int main() 50 { 51 int q,aa,bb,c,d; 52 init(); 53 an[0]=0; 54 for(int i=1; i<30000; i++) 55 { 56 init();///每次計算時記得初始化矩陣 57 ans=mul(ans,pow(A,i-1)); 58 an[i]=an[i-1]+ans.m[0][0]*ans.m[0][0]; 59 } 60 while(cin>>q) 61 { 62 while(q--) 63 { 64 cin>>aa>>bb>>c>>d; 65 ll st=4*aa+bb+1,ed=4*c+d+1; 66 if(st>ed)swap(st,ed); 67 printf("%lld\n",an[ed]-an[st-1]); 68 } 69 } 70 }

HDU-problem-1002-人類史上最大最好的希望事件-矩陣快速冪