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 ;
}