hdu 1588 Gauss Fibonacci

http://acm.hdu.edu.cn/showproblem.php?pid=1588

题意:g(i)=k*i+b,sum(f(g(i)) for 0<=i<n
思路:
根据Fibonacci矩阵的求法,f(i)=mat^i 令mat={1,1,1,0} ,f(g(i))=mat^g(i)=mat^(ki+b) ,sum(f(g(i))=mat^b+mat^(k+b)+...+mat^(ki+b) for 0<=i<n,提取mat^b得:sum(f(g(i))=mat^b+mat^b[mat^(k)+mat^2k...+mat^(ki)] , 问题转化为求 mat^(k)+mat^2k...+mat^(ki)

*做法1:求mat^k,然后用O(i)的时间求sum 结果TLE
*做法2:对等比矩阵进行二分求和,做法如下:
*求得matk=mat^k
*原式=matk+matk^2+...+matk^i
*如果 i 为偶数:原式=(matk+matk^2+...+matk^i/2)+matk^(i/2)(matk+matk^2+...+matk^i/2)
*如果(i)为奇数:那我们干脆先计算前面的i-1个偶数
* 用前面所诉的方法 tmp1=matk+matk^2+...+matk^i/2 tmp2=tmp1*matk^i/2
* 前偶数个的和tmp=tmp1+tmp2
* 最后的结果=tmp+matk^i


代码:

#include<stdio.h>
#include<string.h>
long long k, b,n,M ;
typedef struct Node{
	long long e[2][2] ;
}Matrix ;
Matrix init , eye ;
void Init(){
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++)
			eye.e[i][j] = (i==j) ;	
	}
	init.e[0][0] = init.e[0][1] = init.e[1][0] = 1 ;
	init.e[1][1] =  0; 	
}
Matrix mul(Matrix m1, Matrix m2){
	Matrix c ;
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			c.e[i][j] = 0 ;
			for(int k=0;k<2;k++){
				c.e[i][j] = (c.e[i][j] + m1.e[i][k]*m2.e[k][j]%M) % M ;	
			}	
		}	
	}	
	return c ;
}
Matrix pow(Matrix m1,long long kk){
	Matrix res=eye ,q=m1 ;
	while(kk){
		if(kk & 1){	res = mul(res , q) ;}
		kk >>= 1 ; q = mul(q,q);	
	}
	return res ;
}
Matrix Add(Matrix m1 ,Matrix m2){
	Matrix c ;
	for(int i=0;i<2;i++)
		for(int j=0;j<2;j++){
			c.e[i][j] = ( m1.e[i][j] + m2.e[i][j] ) % M ;
		}	
	return c;
}
Matrix Binarysearch(Matrix m1 , long long kk){
	if(kk == 0)	return eye ;
	if(kk == 1)	return m1 ;
	Matrix res ,t1,t2 ;
	if(kk & 1){
		res = Add( Binarysearch(m1,kk-1) , pow(m1,kk));
	}
	else{
		long long a = kk >> 1;
		t1 = pow(m1 , a);
		t2 = Binarysearch(m1, a);
		res = Add(t2 ,mul(t1 , t2)) ;
	}
	return res ;
}

int main(){
	Matrix t2 , t1 ,res ;
	Init() ;
	while(scanf("%lld%lld%lld%lld",&k,&b,&n,&M)==4){	
		t1 = pow(init , k);
		t2 = pow(init , b);
		res = mul(t2, Add( eye, Binarysearch(t1,n-1) ) );
		printf("%lld\n",res.e[0][1]);
	}
	return 0 ;	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值