HDU 1757 矩阵相乘,快速幂模板题
题意: If x < 10, f(x) = x;
If x >= 10, f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
给出k和mod,求f(k)。
总结: 1、特别注意,矩阵相乘不满足交换律,即a*b != b*a。 2、感觉推方程有点困难。 3、矩阵初始化注意。
f(x-10) 0 0 0 0 0 0 0 0 0 ( first矩阵 )
f(x-9) 0 0 0 0 0 0 0 0 0
f(x-8) 0 0 0 0 0 0 0 0 0
f(x-7) 0 0 0 0 0 0 0 0 0
f(x-6) 0 0 0 0 0 0 0 0 0
f(x-5) 0 0 0 0 0 0 0 0 0
f(x-4) 0 0 0 0 0 0 0 0 0
f(x-3) 0 0 0 0 0 0 0 0 0
f(x-2) 0 0 0 0 0 0 0 0 0
f(x-1) 0 0 0 0 0 0 0 0 0
*
0 1 0 0 0 0 0 0 0 0 ( temp矩阵 )
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1
a9 8 7 6 5 4 3 2 1 0 (这一行是ai)
=
f(x-9) 0 0 0 0 0 0 0 0 0
f(x-8) 0 0 0 0 0 0 0 0 0
f(x-7) 0 0 0 0 0 0 0 0 0
f(x-6) 0 0 0 0 0 0 0 0 0
f(x-5) 0 0 0 0 0 0 0 0 0
f(x-4) 0 0 0 0 0 0 0 0 0
f(x-3) 0 0 0 0 0 0 0 0 0
f(x-2) 0 0 0 0 0 0 0 0 0
f(x-1) 0 0 0 0 0 0 0 0 0
f(x) 0 0 0 0 0 0 0 0 0
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<bitset> #include<vector> #include<set> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f typedef long long ll; const int N = 1e5+10, Maxn = 15; ll k,m=100; struct Mat { ll mat[Maxn][Maxn]; Mat() { mes(mat,0); F(i,0,Maxn) mat[i][i]=1; } } E; Mat first, temp; Mat operator * (Mat a, Mat b) { Mat ans; memset(ans.mat, 0, sizeof(ans.mat)); for (int i = 0; i < Maxn; i++) for (int j = 0; j < Maxn; j++) for (int k = 0; k < Maxn; k++) ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % m; return ans; } Mat operator ^ (Mat a,ll x) { Mat p = E, q = a; while (x) { if(x&1) p = p*q; x>>=1; q = q*q; } return p; } int main() { mes(first.mat, 0); F(i,0,10) first.mat[i][0]=i; while(~scanf("%lld%lld", &k, &m)) { mes(temp.mat, 0); FF(i,0,8) temp.mat[i][i+1]=1; F(i,0,10) { scanf("%lld", &temp.mat[9][9-i]); } if(k<10) { printf("%lld\n", k); continue; } Mat ans= (temp^(k-9))*first; //注意,这里顺序不要反了 printf("%lld\n", ans.mat[9][0]); } return 0; }
矩阵模板
const ll mod = 10, N = 31; struct Mat { ll mat[N][N]; Mat() { mes(mat,0); for(int i=0; i<N; ++i) mat[i][i]=1; //对角线初始化为1,其它为0 } } E; //单位矩阵 Mat Zero; // Zero 要清 0 ll len = n; Mat operator * (Mat a, Mat b) //重载 * ,特别注意,矩阵相乘不满足交换律,即a*b != b*a { Mat ans; memset(ans.mat, 0, sizeof(ans.mat)); for (ll i = 0; i < len; i++) for (ll j = 0; j < len; j++) for (ll k = 0; k < len; k++) ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j]%10) % mod; return ans; } Mat operator ^ (Mat a, ll x) //重载 ^ { Mat p = E, q = a; while (x) { if(x&1) p = p*q; x >>= 1; q = q*q; } return p; } Mat mul(Mat a,Mat b) //函数 * { Mat ans; for(int i=0; i<len; i++) for(int j=0; j<len; j++) { ans.mat[i][j]=0; for(int k=0; k<len; k++) ( ans.mat[i][j] += a.mat[i][k]*b.mat[k][j]%mod ) %= mod; } return ans; } Mat Pow_mod(Mat s, int b){ //函数开方 Mat ans; for(int i=0; i<len; ++i) ans.mat[i][i]=1; while(b) { if(b&1) ans = mul(ans, s); s= mul(s, s); b >>= 1; } return ans; } void prMat(Mat a) { for(ll i=0; i<len; i++) for(ll j=0; j<len; j++) printf("%lld%c", a.mat[i][j], " \n"[j==len-1]); } Mat Add(Mat a, Mat b) { Mat s; for(int i=0; i<len; ++i) for(int j=0; j<len; ++j) s.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % mod; return s; }