J-Sequence HDU-6395 (matrix fast power + analogy idea (first time to apply linear algebra matrix operations here (still very happy)))

Insert picture description here
Insert picture description here
This problem is not just a simple Fibonacci sequence matrix fast exponentiation; there is also a piecewise idea (number theory is also used here): To
solve this problem, I think we should first make the matrix fast exponentiation clear. OK, in fact, the fast power of matrix is ​​the same as the fast power of exponent we usually write (analogous thinking);
first of all,
let ’s talk about the simplest matrix fast power: we can use structure knowledge or class knowledge to write;
here is the structure Body version (solving the simplest Fibonacci sequence calculation):
Insert picture description here
Then:
the calculation (the value of the nth term) Fibonacci sequence is very easy (here is the Mod used, otherwise it will cross the boundary):

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define Mod 100000007
typedef long long ll;
#define N 2//这里表示2*2的矩阵//如果是3*3的  则可以令为N 3 
struct Mu{
  ll	a[N][N];
  Mu(){
  	   memset(a,0,sizeof(a));
  }
};
Mu Multiply(Mu t1,Mu t2){//求两个矩阵相乘 
	  Mu res;
	  for(ll i=0;i<N;i++){
	  	  for(ll j=0;j<N;j++){
	  	  	   for(ll k=0;k<N;k++)
	  	  	   {
	  	  	   	      res.a[i][j]=(res.a[i][j]+t1.a[i][k]*t2.a[k][j])%Mod;
				   }
			}
	  }
	  return res;
} 
Mu QP(Mu x,ll n)//矩阵快速幂 返回结果对象 
{
	   Mu res;
	   res.a[0][0]=res.a[1][1]=res.a[2][2]=1;//单位矩阵
	   while(n){
	   	  if(n&1){
	   	  	   res=Multiply(res,x);
			 }
			 x=Multiply(x,x);
			 n>>=1;
	   } 
	   return res;
}
Mu ans;
ll n,F1=1,F2=1;
void init(){
	//初始化矩阵
  //比如斐波那契数列 
    ans.a[0][0]=ans.a[0][1]=ans.a[1][0]=1;
}
void Ans(){
	 ans=QP(ans,n-2);//算ans^n
	cout<<(ans.a[0][0]*F1+ans.a[0][1]*F2)%Mod<<endl;
}
int main(){
	cin>>n;
	if(n==1) return cout<<F1<<endl,0;
	else if(n==2) return  cout<<F2<<endl,0;
	init();
	Ans();
	return 0;
}

Insert picture description here
Is it very powerful, hehe; but it is far from enough to solve this problem; the
first point of this problem is that the recurrence formula is not easy to find, and the second point is that the segmentation problem is a difficult point (because the normal branch timeout), solve this The AC problem can be solved by two points; just
look at the code (mainly because the parameters passed to the custom class are different from those in Java, I can distinguish it very clearly now!! Hehe);
recurrence formula:
Insert picture description here
Insert picture description here
So because of matrix multiplication The law of associativity is counted from the left;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define Mod 1000000007
struct Mu{
	ll a[3][3];//就是这里我WA了很多次,没有写ll结果自己Debug了半天  我还以为自己把快速幂写错了,太无语了
	Mu(){//构造函数
		  memset(a,0,sizeof(a));
	}
};
Mu mu(Mu t1,Mu t2){
	  Mu res;
	  for(ll i=0;i<3;i++){
	  	  for(ll j=0;j<3;j++){
	  	  	   for(ll k=0;k<3;k++){
	  	  	   	   res.a[i][j]=(res.a[i][j]+t1.a[i][k]*t2.a[k][j])%Mod;
				   }
			}
	  }
	  return res;
}
Mu QP(Mu x,int n){
	Mu res;
	res.a[0][0]=res.a[1][1]=res.a[2][2]=1;
	while(n){
		  if(n&1){
		  	   res=mu(res,x);
		  }
		  x=mu(x,x);
		  n>>=1;
	}
	return res;
}
//int Period(int P,int i){
//	  int j;
//
//	  for(j=i;(P/i)==(P/j);j++);
//	  return j;
//}
int main(){
	ll T,A,B,C,D,P,n;
	scanf("%lld",&T);
	while(T--){
		  scanf("%lld %lld %lld %lld %lld %lld",&A,&B,&C,&D,&P,&n);
		   if(n==1) {printf("%lld\n",A);continue;}
		  if(n==2) {printf("%lld\n",B);continue;}
		  ll j;
		  	Mu s,ans;
		  for(int i=3;i<=n;i=j+1){
		  	//memset(s.a,0,sizeof(s.a));//因为每次都需要置为0
		  	s.a[0][0]=D;s.a[0][1]=C;s.a[0][2]=P/i;
		  	s.a[1][0]=1;
		  	s.a[2][2]=1;
		  	//算阶段幂
	       if(i>P){//这里是算最后一次
	       	    ans=QP(s,n-i+1);
	       	    B=(ans.a[0][0]*B%Mod+ans.a[0][1]*A%Mod+ans.a[0][2])%Mod;
				 break;    
		   }
		     j=min(n,P/(P/i));//这里必须要比最小值,用如果大于了n就不成立了
		     ans=QP(s,j-i+1);
		   ll t1=(ans.a[0][0]*B+ans.a[0][1]*A+ans.a[0][2])%Mod;//这里就是为什么需要更新A,B,因为由上面图的分析可以知道
		   ll t2=(ans.a[1][0]*B+ans.a[1][1]*A+ans.a[1][2])%Mod;
		   B=t1;A=t2;//因为这里的矩阵是倒起来算的,所以需要每次更新A,B
		  }
		  printf("%lld\n",B);//最后输出B
		  
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_44555205/article/details/97970000