关于矩阵运算
  • 板块学术版
  • 楼主REMAC
  • 当前回复5
  • 已保存回复5
  • 发布时间2023/8/9 19:11
  • 上次更新2023/11/3 04:54:03
查看原帖
关于矩阵运算
386892
REMAC楼主2023/8/9 19:11

rt,本人在『STAOI』G - Round 3 T3 中使用了未展开的矩阵乘法,喜提 TLE55pts。代码下附。

未展开的矩阵乘法常数很大么?不展开有何卡常办法?

#include<bits/stdc++.h>
using namespace std;

int M;
#define int long long


struct Mat {
	int a[3][3],r,c;
	
	Mat(int r,int c,int k):r(r),c(c){
		memset(a,0,sizeof a);
		for(int i=1;i<=min(c,r);i++) a[i][i]=k;
	}
	
	Mat():r(2),c(2){
		memset(a,0,sizeof a);
		for(int i=1;i<=min(c,r);i++) a[i][i]=1;
	}
	
	const int* operator[](const int p) const {
		return a[p];
	}
	
	int* operator[](const int p) {
		return a[p];
	}
	
	Mat operator*(const Mat b) const {
		Mat ret(r,b.c,0);
		for(int i=1;i<=r;i++) {
			for(int j=1;j<=b.c;j++) {
				for(int k=1;k<=c;k++) {
					ret[i][j]+=a[i][k]*b[k][j]%M;
					ret[i][j]%=M;
				}
			}
		}
		return ret;
	}
};

Mat pow(Mat b,int p) {
		Mat ret(b.r,b.c,1);
		while(p>0) {
			if(p&1) ret=ret*b;
			b=b*b;
			p>>=1;
		}
		return ret;
	}
	
using Plm=pair<long long, Mat>;

map<long long,Plm> mp;
Mat raw(1,2,0);
Mat fib(2,2,0);
	
Mat calc(int n) {
	Mat sp;
	if(mp.count(M))
		sp=pow(mp[M].second,n/mp[M].first)*pow(fib,n%mp[M].first);
	else sp=pow(fib,n);
	mp[M]=Plm{n,sp};
	return raw*sp;
}

struct ask {
	int M,n,id;
	bool operator<(const ask b) const {
		return M!=b.M?M<b.M:n<b.n;
	}
}q[200010];

int ans[200010];


main() {
	ios::sync_with_stdio(0);
	cout.tie(0);
	cin.tie(0);
	
	raw[1][1]=0;
	raw[1][2]=1;
	
	fib[1][1]=0;
	fib[1][2]=1;
	fib[2][1]=1;
	fib[2][2]=1;
	int T;
	cin>>T;
		
	for(int i=1;i<=T;i++) {
		cin>>q[i].n>>q[i].M;
		q[i].id=i;
	}
	sort(q+1,q+1+T);
	for(int i=1;i<=T;i++) {
		M=q[i].M;
		Mat res=calc(q[i].n);
		ans[q[i].id]=(res[1][2]%M*((res[1][1]*res[1][1]%M+res[1][1])%M))%M;
	}
	for(int i=1;i<=T;i++) {
		cout<<ans[i]<<endl;
	}
}

以及,个人习惯用结构体,需不需要换成 C 风格》/kel

2023/8/9 19:11
加载中...