题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2842
题意:解开第k个环需要先解开前(k-2)个环,并留有第(k-1)环。问解开n环最少需要几步。
题解:
设f(n)表示解开第n环。
1. 解开n环不能一下子把n-1全解开了,否则第n个就没法拿掉了。
2. 得先拿掉第n个:先完成f(n-2),然后再拿掉第n环。
3. 然后放回前(n-2),其实这也是f(n-2),因为是一个逆的过程。
4. 最后就变成完成f(n-1)了,所以f(n) = f(n-2)+1 + f(n-2) + f(n-1)。
下面是自己写的矩阵模版:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 4 const int maxn=3,mo=200907;//矩阵阶数,取余 5 int N=2,n;//N为矩阵实际阶数减1 6 7 struct mat{ 8 long long c[maxn][maxn]; 9 void init(){F(i,0,N)F(j,0,N)c[i][j]=0;} 10 mat operator*(mat b){ 11 mat M; M.init(); 12 F(i,0,N)F(j,0,N)F(k,0,N)M.c[i][j]=(c[i][k]*b.c[k][j]+M.c[i][j])%mo; 13 return M; 14 } 15 mat operator+(mat b){ 16 mat M; M.init(); 17 F(i,0,N)F(j,0,N)M.c[i][j]=(c[i][j]+b.c[i][j])%mo; 18 return M; 19 } 20 mat operator^(int k){ 21 mat ans,tmp;ans.init(); 22 F(i,0,N)F(j,0,N)tmp.c[i][j]=c[i][j]; 23 F(i,0,N)ans.c[i][i]=1; 24 while(k){ 25 if(k&1)ans=ans*tmp; 26 k>>=1,tmp=tmp*tmp; 27 } 28 return ans; 29 } 30 }A[2],ans; 31 32 int main(){ 33 A[0]=(mat){1,2,1,1,0,0,0,0,1},A[1]=(mat){2,0,0,1,0,0,1,0,0}; 34 while(~scanf("%d",&n),n){ 35 if(n<=2)printf("%d ",n); 36 else ans=(A[0]^(n-2))*A[1],printf("%lld ",ans.c[0][0]); 37 } 38 return 0; 39 }