矩阵快速幂

算法封装模板

点击查看代码
struct matrix {
	vector<vector<int>>a,b;
	int n;
	matrix (int n1):n(n1),a(n1,vector<int>(n1,0)),b(n1,vector<int>(n1,0)){}
  	matrix operator-(const mat& T) const {
    matrix res(n);
    for(int i = 0; i < n; ++i)
	    for (int j = 0; j < n; ++j) {
	        res.a[i][j] = (a[i][j] - T.a[i][j]) % mod;
	    }
    	return res;
  	}
	matrix operator+(const mat& T) const {
		matrix res(n);
		for (int i = 0; i < n; ++i)
			for (int j = 0; j < n; ++j){
			    res.a[i][j] = (a[i][j] + T.a[i][j]) % mod;
			}
		return res;
	}
  	matrix operator*(const mat& T) const {
	   	matrix res(n);
	   	int r;
	   	for (int i = 0; i < n; ++i)
	     	for (int k = 0; k < n; ++k) {
	       		r = a[i][k];
	       		for (int j = 0; j < n; ++j)
	          		res.a[i][j] += T.a[k][j] * r, res.a[i][j] %= mod;
	      	}
	    return res;
   }
	matrix operator^(int x) const {
	    matrix res(n), bas(n);
	    for (int i = 0; i < n; ++i) res.a[i][i] = 1;
	    for (int i = 0; i < n; ++i)
	    	for (int j = 0; j < n; ++j) bas.a[i][j] = b[i][j]%mod;
	    while (x) {
	      	if (x & 1) res = res * bas;
	      	bas = bas * bas;
	      	x >>= 1;
	    }
	    return res;
	}
};

例题
[例题](https://atcoder.jp/contests/abc293/tasks/abc293_e?lang=en)

思路
从题意可知,这个题明显不能用逆元,因为用费马小定理的限制是模数mod必须是质数
而使用扩展欧几里得求逆元的条件是这个公式中\(ax \equiv 1 \pmod m\)必须满足\(gcd(a,m)==1\)条件,很明显这个题目是不满足的,
所以我们可以考虑使用矩阵加速来解决这个问题,\(x<=1e12\),因此使用\(log(n)\)的时间复杂度是可以满足的.
推式子可以知道

\[f(n) = a \times f(n-1) + 1 \times 1 \]

\[\begin{pmatrix} f_x \\[6pt] 1 \end{pmatrix} = \begin{pmatrix} a & 0 \\[3pt] 1 & 1 \end{pmatrix}^{x} \; \begin{pmatrix} f_0 \\[6pt] 1 \end{pmatrix} \]

所以最后只用求出

\[T^x \;=\; \begin{pmatrix} p & q \\ r & s \end{pmatrix} \]


$$ \begin{pmatrix} f_x \\ 1 \end{pmatrix} = T^x \begin{pmatrix} f_0 \\ 1 \end{pmatrix} = \begin{pmatrix} p & q \\ r & s \end{pmatrix} \begin{pmatrix} f_0 \\ 1 \end{pmatrix} = \begin{pmatrix} pf_0 + q \\ rf_0 + s \end{pmatrix} $$
$$ f_x \;=\; p\,f_0 + q. $$
以下是代码
点击查看代码
#include<bits/stdc++.h>
#define fi first
#define se second 
#define int long long
#define PII pair<int,int>
using namespace std;
const int N=5e6+10,M=1e9,mod=1e9+7;
int MOD;
int qim(int a,int k,int m){
	int res=1;
	while(k){
		if(k&1)res=res*a%m;
		k>>=1;
		a=a*a%m;	
	}
	return res;
}
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}
int lcm(int a,int b){
	return a*b/gcd(a,b);
}
struct mat {
	vector<vector<int>>a;
	int n;
	mat (int n1):n(n1),a(n,vector<int>(n,0)){}
  	mat operator-(const mat& T) const {
    mat res(n);
    for(int i = 0; i < n; ++i)
	      for (int j = 0; j < n; ++j) {
	        res.a[i][j] = (a[i][j] - T.a[i][j]) % MOD;
	      }
    	return res;
  	}
		mat operator+(const mat& T) const {
		    mat res(n);
		    for (int i = 0; i < n; ++i)
			    for (int j = 0; j < n; ++j){
			        res.a[i][j] = (a[i][j] + T.a[i][j]) % MOD;
			    }
		    return res;
		}
  		mat operator*(const mat& T) const {
	    mat res(n);
	    int r;
	    for (int i = 0; i < n; ++i)
	      for (int k = 0; k < n; ++k) {
	        r = a[i][k];
	        for (int j = 0; j < n; ++j)
	          	res.a[i][j] += T.a[k][j] * r, res.a[i][j] %= MOD;
	      	}
	    	return res;
	  	}
	  mat operator^(int x) const {
	    mat res(n), bas(n);
	    for (int i = 0; i < n; ++i) res.a[i][i] = 1;
	    for (int i = 0; i < n; ++i)
	      for (int j = 0; j < n; ++j) bas.a[i][j] = a[i][j] % MOD;
	    while (x) {
	      if (x & 1) res = res * bas;
	      bas = bas * bas;
	      x >>= 1;
	    }
	    return res;
	  }
};
//int e[N],ne[N],h[N],idx,w[N],in[N],out[N];
//void add(int a,int b,int c){
//	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
//}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int _=1;
	//cin>>_;
	while(_--){
		int a,x,m;cin>>a>>x>>m;
		MOD=m;
		mat ma(2);
		ma.a[0][0]=a%m,ma.a[0][1]=1;
		ma.a[1][1]=1;
		ma=(ma^x);
		cout<<ma.a[0][1]<<'\n';
	}
	return 0;
}

用矩阵加速$log(n)$解决斐波那契数列: $$ f(n)=f(n-1)+f(n-2) $$
因此可以构造矩阵 $$ \begin{pmatrix} f_n \\ f_{n-1} \end{pmatrix} = \begin{pmatrix} f_{n-1} \times 1 + f_{n-2} \times 1\\ f_{n-1} \times 1 + f_{n-2} \times 0\\ \end{pmatrix} = \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix} \times \begin{pmatrix} f_{n-1}\\ f_{n-2} \end{pmatrix} $$ 因此可以化成 $$ \begin{pmatrix} f_{n-1}\\ f_{n-2} \end{pmatrix} = \begin{pmatrix} 1 & 1\\ 1 & 0 \end{pmatrix} ^{n-2} \times \begin{pmatrix} f_{2}\\ f_{1} \end{pmatrix} $$
posted @ 2025-04-30 10:37  xzx_com  阅读(23)  评论(0)    收藏  举报