标签:des style blog http io ar color os sp
http://acm.hdu.edu.cn/showproblem.php?pid=1588
题目解析:
用于构造斐波那契的矩阵为
0,1
1,1
设这个矩阵为A。
sum=f(b)+f(k+b)+f(2*k+b)+f(3*k+b)+........+f((n-1)*k+b)
<=>sum=A^b+A^(k+b)+A^(2*k+b)+A^(3*k+b)+........+A^((n-1)*k+b)
<=>sum=A^b+A^b*(A^k+A^2*k+A^3*k+.......+A^((n-1)*k))(1)
设矩阵B为A^k;
那么(1)式为
sum=A^b+A^b*(B+B^2+B^3+......+B^(n-1));
显然,这时候就可以用二分矩阵做了,括号内的就跟POJ 3233的形式一样了。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> #define inf 0x3f3f3f3f #define LL __int64//int就WA了 using namespace std; struct ma { LL a[2][2]; } init,res,B,C; int mod,k,b,n,K; void Init() { init.a[0][0]=0; init.a[0][1]=1; init.a[1][0]=1; init.a[1][1]=1; } ma Mult(ma x,ma y) { ma tmp; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { tmp.a[i][j]=0; for(int z=0; z<2; z++) { tmp.a[i][j]=(tmp.a[i][j]+x.a[i][z]*y.a[z][j])%mod; } } } return tmp; } ma Pow(ma x,int K) { ma tmp; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) tmp.a[i][j]=(i==j); } while(K!=0) { if(K&1) tmp=Mult(tmp,x); K>>=1; x=Mult(x,x); } return tmp; } ma Add(ma x,ma y) { ma tmp; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { tmp.a[i][j]=(x.a[i][j]+y.a[i][j])%mod; } } return tmp; } ma Sum(ma x,int K) { ma tmp,y; if(K==1) return x; tmp=Sum(x,K/2); if(K&1) { y=Pow(x,K/2+1); tmp=Add(Mult(y,tmp),tmp); tmp=Add(tmp,y); } else { y=Pow(x,K/2); tmp=Add(Mult(y,tmp),tmp); } return tmp; }
/*另外一种写法
matrix Sum(matrix x, int k)
{
if(k==1) return x;
if(k&1)
return Add(Sum(x,k-1),Pow(x,k)); //如果k是奇数,求x^k+sum(x,k-1)
matrix tmp;
tmp=Sum(x,k>>1);
return Add(tmp,Mult(tmp,Pow(x,k>>1)));
}
*/ int main() { while(scanf("%d%d%d%d",&k,&b,&n,&mod)!=EOF) { Init(); B=Pow(init,k); C=Pow(init,b); res=Sum(B,n-1); res=Mult(C,res); res=Add(C,res); printf("%I64d\n",res.a[1][0]); } return 0; }
标签:des style blog http io ar color os sp
原文地址:http://www.cnblogs.com/zhangmingcheng/p/4133896.html