The Nth Item(矩阵快速幂(非结构体))

在这里插入图片描述
在这里插入图片描述
这道题题意很简单;但是如果你用struct矩阵快速幂就是t,我就是QAQ;最后自己手写了两个函数来搞快速幂,然后才AC的;
因为我发现如果用结构体的话,那么就会调用复制构造函数,这样时间复杂度就上升了;
现在说说这道题的意思吧:
题意:就是上面那个等式,很明显如果以前有经验的一看就是矩阵快速幂:
可以很明显的构造出一个矩阵出来:
在这里插入图片描述
然后就可以知道它:
在这里插入图片描述
如果你不清楚为什么是n-1的话,你可以这样想一想;
如果n取3;那么就是:
在这里插入图片描述
所以可以推出来指数为n-1;
然后就很简单了直接矩阵快速幂就OK了;
但是你会发现t了?why????
其实比赛的时候我也不知道为啥;但是赛后我才知道因为n是异或的值,所以可能异或到以前出现过的值,如果以前出现过n了,那么我就不需要计算了吧;所以我就可以用一个map来标记是否算过以n-1为指数的矩阵快速幂;就不用再去算了,所以可以自己手写三个函数去实现快速幂;那么最后答案就是Fn=a[0][0]*F1+a[0][1]*F0;可以知道F0=0所以就没必要写后面的了;就直接:
Fn=a[0][0]*F1;
所以这道题就AC了,说实话这个题也是比较坑的,1.重复出现,2.结构体快速幂有复制构造函数所以就不能用struct去写;
以后吸取教训了,快速幂最好都自己去手写一遍,免得t了;
常识补充其实map还可以用unordered_map来标记,只不过这里没用到查找功能,所以一个简单的map就够了;
AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Mod=998244353;
#define N 2//这里表示2*2的矩阵//如果是3*3的  则可以令为N 3 
map<ll,ll> A;
ll a[N][N],one[N][N],t[N][N];//a是初始化矩阵,one是单位矩阵,t是临时矩阵
void Multiply(ll b[N][N],ll c[N][N]){//求两个矩阵相乘存在b中 ,因为二维数组传的是首地址,所以实参会被修改
    for(int i=0;i<N;i++){
    	   for(int j=0;j<N;j++){
    	   	   t[i][j]=0;
		   }
	}
	  for(ll i=0;i<N;i++){
	  	  for(ll j=0;j<N;j++){
	  	  	   for(ll k=0;k<N;k++)
	  	  	   {
	  	  	   	      t[i][j]=(t[i][j]+b[i][k]*c[k][j])%Mod;//算两个矩阵的乘法
				   }
			}
	  }
	  for(int i=0;i<N;i++){
    	   for(int j=0;j<N;j++){
    	   	   b[i][j]=t[i][j];//复制给b
		   }
	}
} 
void QP(ll x[N][N],ll n)//答案存在单位矩阵中 
{
	   while(n){
	   	  if(n&1){
	   	  	   Multiply(one,x);
			 }
			   Multiply(x,x);
			 n>>=1;
	   } 
}
void init(){//初始化构造矩阵+单位矩阵
	  a[0][0]=3;a[0][1]=2;a[1][0]=1;//初始化矩阵 
	  a[1][1]=0;
	  one[1][0]=one[0][1]=0;
	  for(int i=0;i<2;i++)one[i][i]=1;//初始化单位矩阵 
}
int main(){
		ios::sync_with_stdio(false);//关闭同步
	ll f1=1;
	ll Q,n,ans=0;
	cin>>Q>>n;
	while(Q--){
        if(A[n]){//检查是否以n-1为幂是否计算过了
        	ans^=A[n];
		}else{
			init();
			QP(a,n-1);
			A[n]=one[0][0]*f1;
			ans^=A[n];
			n=n^(A[n]*A[n]); 
		}   
    }
   prinf("%lld",ans);//输出答案
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值