代码改变世界

杭电2855 Fibonacci Check-up

2012-02-15 08:45  javaspring  阅读(165)  评论(0编辑  收藏  举报

        是一道数论方面的题,融合了矩阵二分幂和多项式定理以及斐波那契数列的一道题。先用公式可以推出来,之后用矩阵二分幂就可以了。



关于矩阵二分幂,实际上就是矩阵的乘法,由于矩阵满足结合律,故可以用平方来计算,就达到了log(n)的复杂度,由于n可能为奇数,可能为偶数,所以当n为奇数时,还需要乘以初始矩阵。

ac代码:

#include <iostream>
#include <cmath>
#include <stdio.h>
using namespace std;
int m;
int matrix[2][2];//存储结果的矩阵
void cheng(int n){
  int x,y,z,w;
  //矩阵乘法运算
  x=((matrix[0][0]%m)*(matrix[0][0]%m))%m+((matrix[0][1]%m)*(matrix[1][0]%m))%m;
  y=((matrix[0][0]%m)*(matrix[0][1]%m))+((matrix[0][1]%m)*(matrix[1][1]%m));
  z=((matrix[1][0]%m)*(matrix[0][0]%m))+((matrix[1][1]%m)*(matrix[1][0]%m));
  w=((matrix[1][0]%m)*(matrix[0][1]%m))+((matrix[1][1]%m)*(matrix[1][1]%m));
  matrix[0][0]=x;matrix[0][1]=y;matrix[1][0]=z;matrix[1][1]=w;
  if(n%2){//乘初始矩阵
    x=(matrix[0][0]%m+matrix[0][1]%m)%m;y=matrix[0][0]%m;
	z=(matrix[1][0]%m+matrix[1][1]%m)%m;w=matrix[1][0]%m;
	matrix[0][0]=x;matrix[0][1]=y;matrix[1][0]=z;matrix[1][1]=w;
  }
  //取余运算
  matrix[0][0]%=m;
  matrix[0][1]%=m;
  matrix[1][0]%=m;
  matrix[1][1]%=m;
}
void dfs(int n){
	if(n==0){
	  matrix[0][1]=0;return;
	}
	else if(n==1){
	  matrix[0][1]=1;return;
	}
    dfs(n/2);
	if(n%2){//根据n的奇偶性判断是否需要乘初始矩阵
	  cheng(1);
	}
	else
		cheng(2);
}
int main(){
	//freopen("1.txt","r",stdin);
  int ncase;//数据组数
  scanf("%d",&ncase);
  while(ncase--){
    int n;
	scanf("%d%d",&n,&m);
	matrix[0][0]=1;matrix[0][1]=1;
	matrix[1][0]=1;matrix[1][1]=0;
	n=n*2;
	dfs(n);//求结果
	printf("%d\n",matrix[0][1]%m);
  }
  return 0;
}