首先感叹下矩阵的强大,真心强大!
然后推荐下 Matrix67 大神的神作:十个利用矩阵乘法解决的经典题目
大神说的很明白了,我觉得再说啥都多余了,请直接去大神那里看吧,我只是刷了几道简单的入门题,贴下代码,和大家交流下:
hdu1575 Tr A
矩阵乘法 + 快速幂,很简单
代码:
#include
const int mod = 9973;
const int N = 11;
int n;
struct prog{
int a[N][N],i,j;
void init(){
for(i=0;i=1){
if(k&1)ans=matrixmult(ans,s);
k=k>>1;
s=matrixmult(s,s);
}
return ans;
}
int main()
{
int i,j,k,cases;
prog s;
scanf("%d",&cases);
while(cases--)
{
scanf("%d%d",&n,&k);
for(i=0;i
这个题有点意思,我是没想到怎么处理,这里有篇给力的文章:
http://www.cnblogs.com/Knuth/archive/2009/09/04/1559951.html
他给了两个思路,亚伟用第一个方法过的(代码在这),我用的第二个方法:
/*
A^b*( I + A^k + (A^k)^2 + .... + (A^k)^(N-1) )
设A^k=B
我们来设置这样一个矩阵
B I
O I
其中O是零矩阵,I是单位矩阵
将它乘方,得到
B^2 I+B
O I
乘三方,得到
B^3 I+B+B^2
O I
乘四方,得到
B^4 I+B+B^2+B^3
O I
既然已经转换成矩阵的幂了,继续用我们的二分或者二进制法,直接求出幂就可以了
*/
#include
#include
#define INT __int64
struct prog{
INT a[2][2];
void init(){
a[0][0]=a[0][1]=a[1][0]=1;
a[1][1]=0;
}
/* 斐波那契矩阵
1,1
1,0
*/
void Print(){//打印输出,方便检查
puts("***********************");
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)printf("%d ",a[i][j]);
puts("");
}puts("***********************");
}
};
struct prog_x{//四位构造矩阵
INT a[4][4];
void init(){
memset(a,0,sizeof(a));
a[0][2]=a[1][3]=a[2][2]=a[3][3]=1;
}
/*
0,0,1,0
0,0,0,1
0,0,1,0
0,0,0,1
*/
void Print(){//打印输出,方便检查
puts("***********************");
for(int i=0;i<4;i++){
for(int j=0;j<4;j++)printf("%d ",a[i][j]);
puts("");
}puts("***********************");
}
};
int mod;
prog matrixmult(prog a,prog b){
int i,j,k;
prog c;
for(i=0;i<2;i++){
for(j=0;j<2;j++){
c.a[i][j]=0;
for(k=0;k<2;k++)
c.a[i][j]+=((a.a[i][k]*b.a[k][j])%mod);
c.a[i][j]%=mod;
}
}
return c;
}
prog mult(prog s,int k){
prog ans;
ans.init();
while(k>=1){
if(k&1)ans=matrixmult(ans,s);
k=k>>1;
s=matrixmult(s,s);
}
return ans;
}
prog_x matrixmult_x(prog_x a,prog_x b){
int i,j,k;
prog_x c;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
c.a[i][j]=0;
for(k=0;k<4;k++)
c.a[i][j]+=((a.a[i][k]*b.a[k][j])%mod);
c.a[i][j]%=mod;
}
}
return c;
}
prog_x mult_x(prog_x s,int k){
prog_x ans;
int i,j;
for(i=0;i<4;i++){
for(j=0;j<4;j++)ans.a[i][j]=s.a[i][j];
}
while(k>0){
if(k&1)ans=matrixmult_x(ans,s);
k=k>>1;
s=matrixmult_x(s,s);
}
return ans;
}
int main()
{
int k,b,n;
while(~scanf("%d%d%d%d",&k,&b,&n,&mod))
{
prog B,tmp;
B.init();
B=mult(B,k-1); //B=A^k
/*tmp=A^b,当b==0的时候,tmp=E*/
if(b==0){
tmp.a[0][0]=tmp.a[1][1]=1;
tmp.a[0][1]=tmp.a[1][0]=0;
}
else{
tmp.init();
tmp=mult(tmp,b-1);
}
prog_x s_x;
s_x.init();
s_x.a[0][0]=B.a[0][0]; //将B=A^k填充进构造矩阵的左上角
s_x.a[0][1]=B.a[0][1];
s_x.a[1][0]=B.a[1][0];
s_x.a[1][1]=B.a[1][1];
//s_x.Print();
s_x=mult_x(s_x,n-1);
prog ans; //取出右上角的2*2的部分
ans.a[0][0]=s_x.a[0][2];
ans.a[0][1]=s_x.a[0][3];
ans.a[1][0]=s_x.a[1][2];
ans.a[1][1]=s_x.a[1][3];
ans=matrixmult(ans,tmp);
printf("%d\n",ans.a[0][1]%mod);
}
return 0;
}
最简单的,有人说过是雅礼下至3岁幼童都会的一道题,= =!
#include
struct prog{
int a[2][2];
void init(){
a[1][1]=a[0][1]=a[1][0]=1;
a[0][0]=0;
}
};
prog matrixmul(prog a,prog b){
int i,j,k;
prog c;
for(i=0;i<2;i++){
for(j=0;j<2;j++){
c.a[i][j]=0;
for(k=0;k<2;k++)
c.a[i][j]+=(a.a[i][k]*b.a[k][j]);
c.a[i][j]%=10000;
}
}
return c;
}
prog mul(prog s,int k){
prog ans;
ans.init();
while(k>=1){
if(k&1)ans=matrixmul(ans,s);
k=k>>1;
s=matrixmul(s,s);
}
return ans;
}
int main()
{
int n;
while(scanf("%d",&n),n!=-1){
if(!n){
printf("0\n");continue;
}
prog s;
s.init();
s=mul(s,n-1);
printf("%d\n",s.a[0][1]%10000);
}
return 0;
}
矩阵的等比数列和,这个用二分实现,表示很经典,很强大,代码不是自己的,贴来Ym,理解:
/*
递归求解
K为偶数的时候不需要计算大括号里面的那一项
S_(K) = A+A^2+A^3+...+A^K
= (1+A^(K/2)) * (A+A^2+A^3+...+A^(K/2)) + {A^K}
= (1+A^(K/2)) * (S_(K/2))
*/
#include
const int N = 30;
int n,mod;
struct prog{
int a[N][N],i,j;
void init(){
for(i=0;i=1){
if(k&1)ans=matrixmult(ans,s);
k=k>>1;
s=matrixmult(s,s);
}
return ans;
}
prog matriplus(prog a,prog b){
int i,j;
for(i=0;i>1)); //tmp = 1+A^(k/2)
tmp=matrixmult(tmp,dfs(s,k>>1)); //tmp = ( 1+A^(k/2) )*( A+A^2+A^3+...+A^(K/2) )
if(k&1) tmp=matriplus(tmp,mult(s,k));//奇,偶判断
return tmp;
}
int main()
{
int i,j,k;
prog s;
scanf("%d%d%d",&n,&k,&mod);
for(i=0;i
求图中从一个点到另一个点恰好经过K条边的最短路径的权值和
这个题需要改下 矩阵乘法 以及 矩阵快速幂 的函数,把矩阵乘法里面的乘改成类似 floyd 的松弛(因为求的是最短路径权值和),还有要注意的是,这个题的矩阵规模较大,离散处理后也有 200*200 ,所以这个矩阵是不能定义在结构体内部的,用全局变量好了,我就是这么干的。
代码:
#include
#include
#include
#define min(a,b) ((a)<(b))?(a):(b)
const int N = 205;
const int INF = 1000000100;
int m,p[1001];
int ans[N][N];
void matrixmult(int a[N][N],int b[N][N]){
int i,j,k;
int c[N][N];
for(i=0;i0){
if(k&1) matrixmult(ans,s);
k=k>>1;
matrixmult(s,s);
}
}
int main()
{
int mat[N][N];
int i,j,n,t,s,e,from,to,val;
while(~scanf("%d%d%d%d",&n,&t,&s,&e))
{
for(i=0;i