ZZY的寵物
Time Limit: 1000MS
Description
ZZY領養了一對剛剛出生的不知名小寵物..巨萌巨可愛!!...小寵物的生命為5個單位時間並且不會在中間出意外翹辮子(如:從0出生能活到5但活不到6)..小寵物經過2個單位時間成熟..剛剛成熟的一對小寵物能立即生育6隻新的小寵物(如:從0出生的一對在2時成熟並進行第一次生育)...小寵物是很忠誠的..不會在中途換伴侶..每對小寵物生育一次這一對的生育能力就會降低2個..也就是說一對小寵物在第二次生育時就只能生4個了..小寵物成熟後每個單位時間都會儘力的生育(例:從0出生的一對..2時間生6個..3時間生4個..4時間生2個...5時間生不出..6時間這一對已經掛了..)..生育出來的新小寵物會繼續這個過程..
ZZY想知道從單位時間0開始..經過M個單位時間(時間為M時)將有多少只活著的小寵物(0時刻有2隻小寵物)
因為ZZY隱隱地覺得什麼地方怪怪的...所以請將這個數目mod10000
Input
多組資料讀到EOF
每組資料一行:
M ( 0<=M<=2000000000 )
最多500組資料
Output
每組輸出一行為 Case 組號: 答案,即M時刻活著的小寵物個數%10000
SampleInput
0
1
2
3
4
8
SampleOutput
Case 1: 2
Case 2: 2
Case 3: 8
Case 4: 12
Case 5: 32
Case 6: 528
Source
ZZY原創的說..
解題報告:
這道題的靈感來自Fibonacci的那個兔子故事...思想是矩陣乘法解遞推數列(應該找不到什麼通項公式吧?反正我沒試過...)
根據題意建立這樣一種數列,數列從0號開始..代表第0個單位時間出生的小寵物...1代表在第1個單位時間出生的小寵物..以此類推..將這個數列某項稱作Z[x]
顯然..當x>=5時..在第x天活著的小寵物數量sum[x] = z[x-5] + z[x-4] + z[x-3] +z[x-2] +z[x-1] + z[x]
再看根據題意 z[x] = z[x-2]/2*6 + z[x-3]/2*4 + z[x-4]/2*2 = z[x-2]*3 + z[x-3]*2 + z[x-4]
顯然這個式子是一個遞推的公式...那麼就可以用矩陣乘法來求解這個遞推公式的第x項是多少...觀察數列建立關於這個遞推數列的"特徵“矩陣..
M = 0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
0 0 1 2 3 0
而初始值為0單位時間的出生情況...可以自己遞推出來...為 A = { 0 , 0 , 0 ,0 ,0 ,2 }
要求第x天出生了多少就用z[x] = A*(M^x)...矩陣乘法用遞迴2分來求解...
要求sum(x)...就分別求出 z[x-5] ,z[x-4] ,z[x-3] ,z[x-2] ,z[x-1] ,z[x]再將這幾個值加起來就行了....
資料:
http://pan.baidu.com/share/link?shareid=66129&uk=1124339433/
標程:
#include<iostream>#include<stdio.h>#include<string.h>using namespace std;struct Matrix{ int s[6][6];}h,p,a;int m,T,ans,k; Matrix Mul(Matrix a,Matrix b){ int i,j,k; Matrix h; memset(h.s,0,sizeof(h.s)); for (k=0;k<6;k++) for (i=0;i<6;i++) for (j=0;j<6;j++) h.s[i][j]=(h.s[i][j]+a.s[i][k]*b.s[k][j])%10000; return h;}Matrix Mdata(int n){ Matrix k; if (n==1) return h; k=Mdata(n/2); k=Mul(k,k); if (n%2) k=Mul(k,h); return k;}int main(){ T=0; memset(a.s,0,sizeof(a.s)); a.s[5][0]=2; memset(h.s,0,sizeof(h.s)); for (int i=0;i<6;i++) h.s[i][i+1]=1; h.s[5][2]=1; h.s[5][3]=2; h.s[5][4]=3; while (~scanf("%d",&m)) { ans=0; k=6; while (k--) { if (m) p=Mul(Mdata(m),a); else p=a; ans+=p.s[5][0]; if (!m) break; m--; } printf("Case %d: %d\n",++T,ans%10000); } return 0;}