ybt6.1章矩阵快速幂题解
矩阵计算
矩阵加减法
要求两个矩阵的行和列相等,两个矩阵对应的位置相加减即可
矩阵乘法
-
一个数 \(k\) 乘矩阵 \(A\),把 \(k\) 乘以矩阵的各个元素,记为 \(kA\)
-
两个矩阵 \(A\) 与 \(B\) 相乘,要求 \(A\) 的列数等于 \(B\) 的行数, \(A\) 尺寸为 \(m*n\),\(B\) 尺寸为 \(n*u\),乘积 \(C\) 的尺寸为 \(m*u\),计算公式为 \(C[i,j]=\sum^n_{k=1}A[i][k]*B[k][j]\)
相当于是固定 \(A\) 的一行,\(B\) 的一列,并把对应的数乘起来再全部加起来作为 \(C[i][j]\) 的答案
矩阵乘法不满足交换律 \(AB\neq BA\) 因为要满足要求 \(A\) 的列数等于 \(B\) 的行数这一限制,而反过来就不一定能满足了
矩阵乘法满足结合律 \((AB)C=A(BC)\) 和分配律 \((A+B)C=AC+BC\),这个手玩一下就好了
T1:
快速幂,板子
T2:
做这种题应该先把递推式子列出来,然后再根据公式列出矩阵,然后往里套就行了
T3:
ybt题解错误
首先这一部分是正确的
然后我们考虑这种形式很矩阵快速幂,就相当于是矩阵 \(A^k=A^{k-1}*A\)
然后A初始化的话就是我们原来的邻接矩阵,自爆的话就将每一个点朝0号节点连一条边,停留的话就将这个点和自己连一条边
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
b.m[u][v]=1;b.m[v][u]=1;
}
for(int i=1;i<=n;i++) b.m[i][0]=1;
for(int i=0;i<=n;i++) b.m[i][i]=1;//这里为什么从0开始,因为我们要把每一秒自爆的方案数留到最后第t秒的时候
最后答案即为
for(int i=0;i<=n;i++){
num+=b.m[1][i];
num%=mod;
}
T4:
T5:
广义矩阵乘法:
只要满足这些性质的都可以进行广义矩阵乘法
然后要先离散化一下,只有200个点可用
T6:
跟狭义斐波那契额数列一样,都是一个套路推出来 \(A\) 矩阵,注意因为给的是 \(a1,a2\) 两项,所以要乘 \(n-2\) 次方
T7:
找规律?dp?
在尝试了好多次dp后我放弃了
然后发现其实是找规律题
我们看题解就行了,讲的听清楚的
具体思路就是对行和列相等的情况分开计算,最后再容斥掉都相等的情况就行了
T8:
首先每个数是独立的,所以我们只用考虑每一个数只要不在所有k个s中出现即可,方案数 \(2^k-1\) 然后因为有n个数,所以是 \((2^k-1)^n\) 种方案
因为n,k都非常之大,所以我们只能用字符串读入,然后又不想写高精,怎么办呢,我写了一个10进制的快速幂,就过了,非常简单
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=70,mod=1e9+7;
int lg[N];
char n[N],k[N];
int quickpow(int x,char *g){
int len=strlen(g+1),ans=1;
// printf("%lld\n",len);
lg[0]=x;
for(int i=1;i<=63;i++){
lg[i]=1;
for(int j=1;j<=10;j++){
lg[i]=lg[i]*lg[i-1]%mod;
}
}
for(int i=len;i>=1;i--){
for(int j=1;j<=g[i]-'0';j++){
// printf("%lld\n",j);
ans=ans*lg[len-i]%mod;
}
}
return ans;
}
signed main(){
cin>>n+1>>k+1;
int cnt=quickpow(2,k);
printf("%lld",quickpow((cnt-1+mod)%mod,n));
}
T9:
推式子太巧妙了!!!
经典转化技巧 \(C^k_n=C^{n-k}_n\)
想到这个式子就完成了
具体推导过程看题解
注意因为输入时 \(n,s,d\) 都大于 \(1e9\) 所以在做乘法时应先将两边都取模