[模板]矩阵十进制快速幂

因为矩阵的运算性质,所以欧拉降幂这种骚操作是假的;

而对于a的b次方非常大时就只能用的十进制快速幂 或者 奇怪的循环节性质解决

例题:

已知数列  F$_{i} =a * F$_{i-1} + b * F$_{i-2} 

给定 a,b,F$_{1},F$_{2} 

求数列第 N 项 同时对 M 取模。

则有公式:\begin{pmatrix} a & b\\0 & 1 \end{pmatrix} $^{n-1} \times \begin{pmatrix} F_1\\F_2 \end{pmatrix} = \begin{pmatrix} F_n\\F_{n-1} \end{pmatrix}

然后套十进制快速幂求解即可

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll MOD;

ll x0, x1, a, b, n;

struct matrix
{
	ll m[2][2];
	matrix()
	{ m[0][0] = 1;m[1][1] = 1;m[0][1] = 0;m[1][0] = 0; }
};

matrix mul(matrix a, matrix b)
{
	matrix tmp;
	for(ll i = 0; i < 2; ++i)
	{
		for(ll j = 0; j < 2; ++j)
		{
			tmp.m[i][j] = 0;
			for(ll k = 0; k < 2; ++k)
				tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
		}
	}
	return tmp;
}

matrix qpow(matrix ra, int n)
{
	matrix ans;
	while(n)
	{
		if(n & 1)
			ans = mul(ans, ra);
		ra = mul(ra, ra);
		n >>= 1;
	}
	
	return ans;
}

ll cal(string x)
{
	matrix base, ret;
	base.m[0][0] = a;
	base.m[0][1] = b;
	base.m[1][0] = 1;
	base.m[1][1] = 0;
	
	for(int i = x.length() - 1; i >= 0; --i) //十进制快速幂
	{
		int k = x[i] - '0';
		if(k > 0)
			ret = mul(ret, qpow(base, k));
		base = qpow(base, 10); 
	}
	
	ll rans = ( ( (ret.m[0][0] * x1) % MOD ) + ( (ret.m[0][1] * x0) % MOD) ) % MOD; 
	
	return rans % MOD;
}

int main()
{
	string s;
	 
	cin >> x0 >> x1 >> a >> b >> s >> MOD;
	
	int len = s.length() - 1;
	
	while(s[len] == '0')
		s[len--] = '9';
		
	--s[len];
	
	cout << ll( cal(s) )  << '\n' ;
	
	return 0;
}

 

posted @ 2019-08-01 20:17  张浦  阅读(110)  评论(0编辑  收藏  举报