矩阵系列 题解

1.洛谷 P1962 斐波那契数列

题意

大家都知道,斐波那契数列是满足如下性质的一个数列:

F n = { 1 ( n ≤ 2 ) F n − 1 + F n − 2 ( n ≥ 3 ) F_n = \left\{\begin{aligned} 1 \space (n \le 2) \\ F_{n-1}+F_{n-2} \space (n\ge 3) \end{aligned}\right. Fn={1 (n≤2)Fn−1+Fn−2 (n≥3)

请你求出 F n   m o d   1 0 9 + 7 F_n \bmod 10^9 + 7 Fnmod109+7 的值。

1 ≤ n < 2 63 1\le n < 2^{63} 1≤n<263。

思路

F i − 1 F i \] = \[ F i − 2 F i − 1 \] ⋅ \[ 0 1 1 1 \] \\begin{bmatrix} F_{i-1} \& F_{i} \\end{bmatrix} =\\begin{bmatrix} F_{i-2} \&F_{i-1} \\end{bmatrix}\\cdot \\begin{bmatrix} 0 \& 1\\\\ 1 \& 1 \\end{bmatrix} \[Fi−1Fi\]=\[Fi−2Fi−1\]⋅\[0111

2.SMOJ 数列1

题意

有一个数列:

f n = { 0 ( n ≤ 2 ) 7 f n − 1 + 6 f n − 2 + 4 × 3 n ( n ≥ 3 ) f_n = \left\{\begin{aligned} 0 \ (n \le 2) \\ 7f_{n-1}+6f_{n-2}+4\times 3^n \ (n\ge 3) \end{aligned}\right. fn={0 (n≤2)7fn−1+6fn−2+4×3n (n≥3)

请你求出 f n   m o d   1 0 9 + 7 f_n \bmod 10^9 + 7 fnmod109+7 的值。

3 ≤ n ≤ 1 0 9 3\le n \le 10^9 3≤n≤109。

思路

f i − 1 f i 4 × 3 i + 1 \] = \[ f i − 2 f i − 1 4 × 3 i \] ⋅ \[ 0 6 0 1 7 0 0 1 3 \] \\begin{bmatrix} f_{i-1} \& f_i \&4\\times3\^{i+1}\\end{bmatrix}=\\begin{bmatrix} f_{i-2} \& f_{i-1} \& 4\\times 3\^i\\end{bmatrix}\\cdot \\begin{bmatrix} 0 \& 6 \& 0\\\\ 1 \& 7 \& 0\\\\ 0 \& 1 \& 3 \\end{bmatrix} \[fi−1fi4×3i+1\]=\[fi−2fi−14×3i\]⋅ 010671003 ## 3.SMOJ 数列2 ### 题意 有一个数列: f n = { 0 ( n ≤ 2 ) 7 f n − 1 + 6 f n − 2 + 4 × 3 n + 5 n ( n ≥ 3 ) f_n = \\left\\{\\begin{aligned} 0 \\ (n \\le 2) \\\\ 7f_{n-1}+6f_{n-2}+4\\times 3\^n+5n \\ (n\\ge 3) \\end{aligned}\\right. fn={0 (n≤2)7fn−1+6fn−2+4×3n+5n (n≥3) 请你求出 f n   m o d   1 0 9 + 7 f_n \\bmod 10\^9 + 7 fnmod109+7 的值。 ### 思路 \[ f i − 1 f i 4 × 3 i + 1 5 ( i + 1 ) 5 \] = \[ f i − 2 f i − 1 4 × 3 i 5 i 5 \] ⋅ \[ 0 6 0 1 0 1 7 0 1 0 0 1 3 1 0 0 1 0 1 0 0 0 0 1 1 \] \\begin{bmatrix} f_{i-1} \& f_i \& 4\\times 3\^{i+1} \& 5(i+1) \& 5 \\end{bmatrix}= \\begin{bmatrix} f_{i-2} \& f_{i-1} \& 4\\times 3\^i \& 5i \& 5 \\end{bmatrix}\\cdot\\begin{bmatrix} 0 \& 6 \& 0 \& 1 \& 0\\\\ 1 \& 7 \& 0 \& 1 \& 0\\\\ 0 \& 1 \& 3 \& 1 \& 0\\\\ 0 \& 1 \& 0 \& 1 \& 0\\\\ 0 \& 0 \& 0 \& 1 \& 1 \\end{bmatrix} \[fi−1fi4×3i+15(i+1)5\]=\[fi−2fi−14×3i5i5\]⋅ 0100067110003001111100001 ## 4.SMOJ 幸运数 ### 题意 小明认为只有数字 4 4 4 和 7 7 7 是幸运数字,其他数字都不是。如果一个整数的每个数字都是幸运数字,那么该整数就是幸运整数。 给出一个数组 n u m b e r s 1... n numbers_{1...n} numbers1...n。 一个长度为 L L L 的幸运数列 A 0... L − 1 A_{0...L-1} A0...L−1 必须同时满足: 1. ∀ i ∈ \[ 0 , L ) \\forall i\\in\[0,L) ∀i∈\[0,L), A i A_i Ai 必须是幸运整数。 2. ∀ i ∈ \[ 0 , L ) \\forall i\\in\[0,L) ∀i∈\[0,L), A i A_i Ai 的最后一个数字必须等于 A \[ i + 1 \] A\[i+1\] A\[i+1\] 的第一个数字。 3. ∀ i ∈ \[ 0 , L ) \\forall i\\in\[0,L) ∀i∈\[0,L),至少存在一个下标 j j j 满足 A i = n u m b e r s j A_i=numbers_j Ai=numbersj。 输出有多少个不同的长度为L的幸运序列,答案模 1234567891 1234567891 1234567891。 对于两个长度都是L的幸运序列 A 0... L − 1 A_{0...L- 1} A0...L−1 和 B 0... L − 1 B_{0...L - 1} B0...L−1,他们被认为是不同序列的条件是: ∃ i , A i ≠ B i \\exist i,A_i\\neq B_i ∃i,Ai=Bi。 1 ≤ n ≤ 50 , 1 ≤ n u m b e r s i ≤ 1 0 9 , 1 ≤ L ≤ 1 0 9 1\\le n\\le 50,1\\le numbers_i\\le 10\^9,1\\le L\\le 10\^9 1≤n≤50,1≤numbersi≤109,1≤L≤109 ### 思路 对所有幸运数分类: 1. 4 4 4 头 4 4 4 尾 2. 4 4 4 头 7 7 7 尾 3. 7 7 7 头 4 4 4 尾 4. 7 7 7 头 7 7 7 尾 用一个桶 c n t cnt cnt 记个数。 令 f i , t y p e f_{i,type} fi,type 表示前 i i i 个幸运数组成的序列中,序列最后一个数种类为 t y p e ∈ \[ 1 , 4 \] type\\in \[1,4\] type∈\[1,4\] 的方案数。 那么容易写出转移式子: f i , 1 = f i − 1 , 1 ⋅ c n t 1 + f i − 1 , 3 ⋅ c n t 1 f_{i,1}=f_{i-1,1}\\cdot cnt_1+f_{i-1,3}\\cdot cnt_1 fi,1=fi−1,1⋅cnt1+fi−1,3⋅cnt1 f i , 2 = f i − 1 , 1 ⋅ c n t 2 + f i − 1 , 3 ⋅ c n t 2 f_{i,2}=f_{i-1,1}\\cdot cnt_2+f_{i-1,3}\\cdot cnt_2 fi,2=fi−1,1⋅cnt2+fi−1,3⋅cnt2 f i , 3 = f i − 1 , 2 ⋅ c n t 3 + f i − 1 , 4 ⋅ c n t 3 f_{i,3}=f_{i-1,2}\\cdot cnt_3+f_{i-1,4}\\cdot cnt_3 fi,3=fi−1,2⋅cnt3+fi−1,4⋅cnt3 f i , 4 = f i − 1 , 2 ⋅ c n t 4 + f i − 1 , 4 ⋅ c n t 4 f_{i,4}=f_{i-1,2}\\cdot cnt_4+f_{i-1,4}\\cdot cnt_4 fi,4=fi−1,2⋅cnt4+fi−1,4⋅cnt4 只需做 L L L 次 dp 即可,但是 L L L 最大去到 1 0 9 10\^9 109,显然会炸。由于操作单调,因此考虑矩阵快速幂优化: \[ f i , 1 f i , 2 f i , 3 f i , 4 \] = \[ f i − 1 , 1 f i − 1 , 2 f i − 1 , 3 f i − 1 , 4 \] ⋅ \[ c n t 1 c n t 2 0 0 0 0 c n t 3 c n t 4 c n t 1 c n t 2 0 0 0 0 c n t 3 c n t 3 \] \\begin{bmatrix} f_{i,1} \& f_{i,2} \& f_{i,3} \& f_{i,4} \\end{bmatrix}=\\begin{bmatrix} f_{i-1,1} \& f_{i-1,2} \& f_{i-1,3} \& f_{i-1,4} \\end{bmatrix}\\cdot\\begin{bmatrix} cnt_1 \& cnt_2 \& 0 \& 0\\\\ 0 \& 0 \& cnt_3 \& cnt_4\\\\ cnt_1 \& cnt_2 \& 0 \& 0\\\\ 0 \& 0 \& cnt_3 \& cnt_3 \\end{bmatrix} \[fi,1fi,2fi,3fi,4\]=\[fi−1,1fi−1,2fi−1,3fi−1,4\]⋅ cnt10cnt10cnt20cnt200cnt30cnt30cnt40cnt3 ### 代码 ```cpp #include using namespace std; #define ll long long const ll N=102,mod=1234567891; struct matrix { ll row,col; ll data[N][N]; matrix(ll r,ll c,ll isI) { row=r; col=c; memset(data,0,sizeof(data)); if(isI) { for(int i=1;i<=row;i++) data[i][i]=1; } } }; matrix operator * (const matrix &a,const matrix &b) { matrix c(a.row,b.col,0); for(int i=1;i<=a.row;i++) for(int j=1;j<=b.col;j++) for(int k=1;k<=a.col;k++) c.data[i][j]=(c.data[i][j]+a.data[i][k]*b.data[k][j]%mod+mod)%mod; return c; } matrix qpow_matrix(matrix a,ll k) { matrix ret(a.row,a.col,1); while(k) { if(k&1)ret=ret*a; a=a*a; k>>=1; } return ret; } ll n,m,a[N]; ll f[N][5],cnt[5]; ll type(string x) { ll sx=x.size(); x='*'+x; for(int i=1;i<=sx;i++) if(x[i]!='4'&&x[i]!='7')return 0; if(x[1]=='4'&&x[sx]=='4')return 1; else if(x[1]=='4'&&x[sx]=='7')return 2; else if(x[1]=='7'&&x[sx]=='4')return 3; else return 4; } vectorluk[N]; int main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) { string a; cin>>a; ll t=type(a); if(!t)continue; bool flag=1; for(auto x:luk[t]) { if(x==a) { flag=0; break; } } if(flag)luk[t].push_back(a),cnt[t]++; } matrix A(1,4,0); matrix B(4,4,0); for(int i=1;i<=n;i++) A.data[1][i]=cnt[i]; B.data[1][1]=B.data[3][1]=cnt[1]; B.data[1][2]=B.data[3][2]=cnt[2]; B.data[2][3]=B.data[4][3]=cnt[3]; B.data[2][4]=B.data[4][4]=cnt[4]; A=A*qpow_matrix(B,m-1); ll ans=0; for(int i=1;i<=4;i++) ans=(ans+A.data[1][i])%mod; printf("%lld",ans); return 0; } ``` ## 5.SMOJ 序列/CF691E Xor-sequences ### 题意 给定一个数集 A A A,现在你需要构造一个长度为 m m m 的序列 B B B,序列 B B B 的元素从数集 A A A 中任意挑选,要求 B B B 中任意相邻的两个数字的异或值二进制表示中 1 1 1 的个数是 3 3 3 的倍数,请问 B B B 的有多少种合法的构造方案?两种方案不同当且仅当存在 b i b_i bi 在 A A A 中的位置不同。 1 ≤ n ≤ 100 , 1 ≤ m ≤ 1 0 18 , 0 ≤ a i ≤ 1 0 18 1\\le n\\le 100,1\\le m\\le 10\^{18},0\\le a_i\\le 10\^{18} 1≤n≤100,1≤m≤1018,0≤ai≤1018 ### 思路 设 f i , j f_{i,j} fi,j 表示选择了 i i i 个数,最后一个数是 a j a_j aj 的方案数(注意数列可以乱序),那么有: f i , j = ∑ k = 1 n f i − 1 , k ⋅ A i , j f_{i,j}=\\sum_{k=1}\^{n}f_{i-1,k}\\cdot\\ A_{i,j} fi,j=k=1∑nfi−1,k⋅ Ai,j 其中 A i , j A_{i,j} Ai,j 表示: A i , j = \[ a j ⨁ a k   m o d   3 = 0 \] A_{i,j}=\\left \[a_j\\bigoplus a_k \\bmod3=0\\right \] Ai,j=\[aj⨁akmod3=0

中括号为艾弗森括号,不难发现 A A A 以对角线对称。

对于每个 ( i , j ) (i,j) (i,j),都要遍历 k ∈ [ 1 , n ] k\in[1,n] k∈[1,n] 来逐一比对一遍是否有 a j ⨁ a k   m o d   3 = 0 a_j\bigoplus a_k \bmod3=0 aj⨁akmod3=0。如此过程,实则与矩阵乘法的运算过程比较相似(这还是比较注意力惊人了,除非你对矩阵无比的熟悉)那么不妨使用矩阵快速幂优化了。最终答案就是:
a n s = ∑ d a t a ( A n − 1 ) ans=\sum data(A^{n-1}) ans=∑data(An−1)

d a t a ( M ) data(M) data(M) 表示一个矩阵 M M M 内所有元素。

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=102,mod=1e9+7;
struct matrix
{
	ll row,col;
	ll data[N][N];
	matrix(ll r,ll c,ll isI)
	{
		row=r;
		col=c;
		memset(data,0,sizeof(data));
		if(isI)
		{
			for(int i=1;i<=row;i++)
			data[i][i]=1;
		}
	}
};
matrix operator * (const matrix &a,const matrix &b)
{
	matrix c(a.row,b.col,0);
	for(int i=1;i<=a.row;i++)
	for(int j=1;j<=b.col;j++)
	for(int k=1;k<=a.col;k++)
	c.data[i][j]=(c.data[i][j]+a.data[i][k]*b.data[k][j]%mod+mod)%mod;
	return c; 
}
matrix qpow_matrix(matrix a,ll k)
{
	matrix ret(a.row,a.col,1);
	while(k)
	{
		if(k&1)ret=ret*a;
		a=a*a;
		k>>=1;
	}
	return ret;
}
ll n,m,a[N];
ll popcnt(ll x)
{
	ll ret=0;
	while(x)
	{
		if(x&1)ret++;
		x>>=1;
	}
	return ret;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)
	scanf("%lld",&a[i]);
	matrix A(n,n,0);
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	A.data[i][j]=(popcnt(a[i]^a[j])%3==0);
	A=qpow_matrix(A,m-1);
	ll ans=0;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	ans=(ans+A.data[i][j])%mod;
	printf("%lld",ans);
	return 0;
}

6.SMOJ 黑板与数字/CF621E Wet Shark and Blocks

(本篇较口胡,见谅)

题意

有 b b b 个黑板,从左往右排成一行。

第 1 1 1 个黑板从左往右写有 n n n 个数字,每个数字是 1 1 1 至 9 9 9 范围内的数字。

把第 1 1 1 个黑板的所有数字复制一份,写到第 2 2 2 个黑板。

把第 1 1 1 个黑板的所有数字复制一份,写到第 3 3 3 个黑板。

把第 1 1 1 个黑板的所有数字复制一份,写到第 b b b 个黑板。

从这 b b b 个黑板中,各取一个数字,构成一个 b b b 位数,要使得这个 b b b 位数模 x x x 的结果是 k k k,求方案数(同一个黑板内取相同的数字算不同方案,因为位置不同),答案模 1 0 9 + 7 10^9+7 109+7。

思路

令 f i , j f_{i,j} fi,j 表示选了 i i i 个格子,模 x x x 余数为 j j j,那么有转移式子:
f i , 10 j + k   m o d   x = f i − 1 , j + n u m ( k ) f_{i,10j+k \bmod x}=f_{i-1,j}+num(k) fi,10j+kmodx=fi−1,j+num(k)

其中 n u m ( k ) num(k) num(k) 表示: n u m ( k ) = ∑ i = 1 n [ a i   m o d   x = k ] num(k)=\sum_{i=1}^n [a_i\bmod x=k] num(k)=i=1∑n[aimodx=k]

再枚举每一位,去到了 Θ ( b x ) \Theta(bx) Θ(bx);但是如此操作,像上几篇题解一样,与矩阵乘法相类似,因此可以考虑矩阵快速幂优化到 Θ ( log ⁡ 2 b ) \Theta(\log_2b) Θ(log2b)

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=111,mod=1e9+7;
ll n,b,k,x,a,yx[N];
struct matrix
{
	ll row,col;//行和列
	ll data[N][N];
	matrix(ll r,ll c,ll isI)
	{
		row=r;
		col=c;
		memset(data,0,sizeof(data));
		if(isI)
		{
			for(int i=0;i<row;i++)
			data[i][i]=1;
		}
	}
};
matrix operator * (const matrix &a,const matrix &b)
{
	matrix c(a.row,b.col,0);
	for(int i=0;i<a.row;i++)
	for(int j=0;j<b.col;j++)
	for(int k=0;k<a.col;k++)
	c.data[i][j]=(c.data[i][j]+a.data[i][k]*b.data[k][j]%mod+mod)%mod;
	return c;
}
matrix qpow_matrix(matrix a,ll k)
{
	matrix res(a.row,a.col,1);
	while(k)
	{
		if(k&1)res=res*a;
		a=a*a;
		k>>=1;
	}
	return res;
}
int main()
{
	scanf("%lld%lld%lld%lld",&n,&b,&k,&x);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a);
		yx[a%x]++;
	}
	matrix A(1,x,0);
	for(int i=0;i<x;i++)
	A.data[0][i]=yx[i];
	matrix B(x,x,0);
	for(int i=0;i<x;i++)
	{
		for(int j=0;j<x;j++)
		{
			ll r=(i*10+j)%x;
			B.data[i][r]+=yx[j];
		}
	}
	A=A*qpow_matrix(B,b-1);
	printf("%lld",A.data[0][k]);
	return 0;
}
相关推荐
SylviaW083 小时前
python-leetcode 63.搜索二维矩阵
python·leetcode·矩阵
小卡皮巴拉3 小时前
【力扣刷题实战】矩阵区域和
开发语言·c++·算法·leetcode·前缀和·矩阵
闯闯爱编程7 小时前
数组与特殊压缩矩阵
数据结构·算法·矩阵
ElseWhereR17 小时前
矩阵对角线元素的和 - 简单
线性代数·矩阵
飞川撸码20 小时前
【LeetCode 热题100】240:搜索二维矩阵 II(详细解析)(Go语言版)
leetcode·矩阵·golang
jndingxin2 天前
OpenCV 图形API(5)API参考:数学运算用于执行图像或矩阵加法操作的函数add()
opencv·webpack·矩阵
y5236483 天前
PowerBI 矩阵,列标题自定义排序
线性代数·矩阵·powerbi
梭七y3 天前
【力扣hot100题】(017)矩阵置零
算法·leetcode·矩阵
进击的jerk4 天前
力扣.旋转矩阵Ⅱ
算法·leetcode·矩阵
幻风_huanfeng4 天前
人工智能之数学基础:矩阵的相似变换的本质是什么?
人工智能·深度学习·线性代数·机器学习·矩阵·相似变换