• HDU3306 Another kind of Fibonacci 矩阵


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - HDU3306


    题意概括

      A0=1,A1=1,AN=X*AN-1+Y*AN-2(N>=2).求SN,SN=A02+A12+…+An2.


    题解

      这题是用矩阵做的,一看(sou)就知道。

      设si为前i项的答案。

      如果要求第i项的ai那么是很简单的。

      构建矩阵:

           ai-1       ai

      ai-2    0      y

      ai-1    1      x

      但是好像没用。

      没错,的确没用。

      我们从二次项考虑:

      si  =si-1+ai2

            =si-1+(xai-1+yai-2)2

         =si-1+x2ai-12+y2ai-22+2xyai-1ai-2

      那么对于ak2形式的已经可以完成递推了。但是有一个棘手的东西,就是akak-1怎么完成递推?

      我们继续推导:

      akak-1=(xak-1+yak-2)ak-1

          =xak-12+yak-1ak-2

      我们发现ak-12ak-1ak-2这两个其实可以按照之前推出来的推,而且不影响后面的。

      于是,我们可以构建递推矩阵:

           si      ai2    ai-12    aiai-1

      si-1        1      0        0      0

      ai-12    x2     x2      1      x

      ai-22    x2     y2      0      0

      ai-1ai-2   2xy    2xy     0      y

      

      意义:

      si    = si-1+x2ai-12+y2ai-22+2xyai-1ai-2

      ai2  =        x2ai-12+y2ai-22+2xyai-1ai-2

      ai-12    =           ai-12

      aiai-1   =         xai-12+                yai-1ai-2

      

      那么原始矩阵的第一行就是

      s1   a12   a02   a1a0

      算出sn,就是把这个原始矩阵乘上n-1个递推矩阵。

      


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    using namespace std;
    const int mod=10007,m=4;
    struct Mat{
    	int v[m][m];
    	Mat (){}
    	Mat (int x){
    		(*this).set(x);
    	}
    	void print(){
    		for (int i=0;i<m;i++,puts(""))
    			for (int j=0;j<m;j++)
    				printf("%5d ",v[i][j]);
    		puts("");
    	}
    	void set(int x){
    		memset(v,0,sizeof v);
    		if (x==1)
    			for (int i=0;i<m;i++)
    				v[i][i]=1;
    	}
    	Mat operator * (Mat x){
    		Mat ans(0);
    		for (int i=0;i<m;i++)
    			for (int j=0;j<m;j++)
    				for (int k=0;k<m;k++)
    					ans.v[i][j]=(ans.v[i][j]+v[i][k]*x.v[k][j])%mod;
    		return ans;
    	}
    	void operator *= (Mat x){
    		(*this)=(*this)*x;
    	}
    }M,Md;
    Mat MatPow(Mat x,int y){
    	Mat ans(1),now=x;
    	while (y){
    		if (y&1)
    			ans*=now;
    		now*=now;
    		y>>=1;
    	}
    	return ans;
    }
    int n,x,y;
    int main(){
    	while (~scanf("%d%d%d",&n,&x,&y)){
    		x%=mod,y%=mod;
    		M.set(0);
    		int newi[m]={2,1,1,1};
    		int newd[m][m]={{1			,0			,0,0},
    						{x*x%mod	,x*x%mod	,1,x},
    						{y*y%mod	,y*y%mod	,0,0},
    						{2*x*y%mod	,2*x*y%mod	,0,y}};
    		memcpy(M.v[0],newi,sizeof newi);
    		memcpy(Md.v,newd,sizeof newd);
    		Md=MatPow(Md,n-1);
    		M*=Md;
    		printf("%d
    ",M.v[0][0]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    织梦调用所有栏目一级二级三级和无限级栏目输出
    织梦添加自定义独立模型缩略图字段官方的一个BUG
    织梦搜索结果增加dede:type、dede:arclist、dede:channelartlist、dede:tag等标签支持
    织梦搜索指定多个栏目的文档
    POJ 1001
    #207 Div.2 B. Flag Day
    sublime Text 2 配置 C++ 编译环境
    1011. 复数类
    1008. 二哥买期货
    MySQL/mariadb知识点——视图管理语句
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU3306.html
Copyright © 2020-2023  润新知