zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    tkinter 类继承的三种方式
    tkinter 的两个例子
    python 测试驱动开发的简单例子
    python 播放 wav 文件
    Python 操作 MongoDB
    【转】如何拿到半数面试公司Offer——我的Python求职之路
    scrapy 保存到 sqlite3
    scrapy 爬取 useragent
    收集的User-Agent
    scrapy 登录
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU3306.html
Copyright © 2011-2022 走看看