初次编辑时间:2010-03-25
AVL树
Time Limit:1000MS Memory Limit:65536K
Total Submit:39 Accepted:15
Description
AVL树是一种平衡树,它的左右子树的高度差不能超过1。一棵高度为h的AVL树的最少节点数的递推公式为S(h)=S(h-1)+S(h-2)+1,已经知道S(1)=1,S(2)=2,现在问题是给定一个h (1<=h<=1000000000),求S(h)%m,2<=m<=1000000000。
Input
输入两个数h,m,其含意如上面所述。
Output
输出S(h)%m
Sample Input
1 100
2 100
3 100
Sample Output
1
2
4
//矩阵法求解
#include<stdio.h>
#include<string.h>
main()
{
int N,M,i,j,k,t,a,b,A[3][3],B[3][3],C[3][3];
const int K=3;
while(scanf("%d%d",&N,&M)!=EOF)
{
if(N==1)
t=1;
else if(N==2)
t=2;
else
{
N-=3;
memset(B,0,sizeof(B));
for(i=0;i<K;i++)
B[0][i]=1;
B[1][0]=1;B[2][2]=1;
memcpy(A,B,sizeof(B));
while(N)
{
if(N%2)
{
for(i=0;i<K;i++)
for(j=0;j<K;j++)
{
for(t=0,k=0;k<K;k++)
{
a=A[i][k];b=B[k][j]; //计算a*b 考虑到精度要求用加法计算,为保证时间效率,用二分求幂法计算、
while(b)
{
if(b%2) t=(t+a)%M;
a=(a+a)%M;
b/=2;
}
}
t%=M;
C[i][j]=t;
}
memcpy(B,C,sizeof(C));
}
for(i=0;i<K;i++)
for(j=0;j<K;j++)
{
for(t=0,k=0;k<K;k++)
{
a=A[i][k];b=A[k][j]; //计算a*b 考虑到精度要求用加法计算,为保证时间效率,用二分求幂法计算、
while(b)
{
if(b%2) t=(t+a)%M;
a=(a+a)%M;
b/=2;
}
}
t%=M;
C[i][j]=t;
}
memcpy(A,C,sizeof(C));
N/=2;
}
t=B[0][0]*2%M;
t=(t+B[0][1])%M;
t=(t+B[0][2])%M;
}
printf("%d\n",t);
}
}