ACM 矩阵题目整理

先从最基础的矩阵快速幂加速递推开始。

HDU 1005 Number Sequence

|f[n-2],f[n-1]|* |0 B| =|f[n-1], B*f[n-2]+A*f[n-1]|=|f[n-1],f[n]|

          |1 A|

建立矩阵如上然后利用快速幂求解即可。答案是mat[0][1]。

#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<set>
#include<string>
#define INF 1000000005
#define LL long long
using namespace std;
const int MAXN =5;
struct Matrix
{
    int n,m;
    int a[MAXN][MAXN];
    void clear(int x=0,int y=0)
    {
        n=x;
        m=y;
        memset(a,0,sizeof(a));
    }
    Matrix operator * (const Matrix &b)const
    {
        Matrix tmp;
        tmp.clear(n,b.m);
        for(int i=0; i<n; ++i)
            for(int j=0; j<b.m; ++j)
                for(int k=0; k<m; ++k)
                {
                    tmp.a[i][j]+=a[i][k]*b.a[k][j];
                    tmp.a[i][j]%=7;
                }
        return tmp;
    }
};
Matrix quickPow(Matrix mat,int n)
{
    Matrix res;
    res.clear(2,2);
    res.a[0][0]=res.a[1][1]=1;
    while(n)
    {
        if(n&1) res=res*mat;
        mat=mat*mat;
        n=n>>1;
    }
    return res;
}
int main()
{
    int A,B,n;
    while(scanf("%d%d%d",&A,&B,&n)!=EOF)
    {
        if(!A&&!B&&!n) break;
        if(n==1||n==2)
        {
            puts("1");
            continue;
        }
        Matrix mat;
        mat.clear(2,2);
        mat.a[0][0]=0;
        mat.a[0][1]=B;
        mat.a[1][0]=1;
        mat.a[1][1]=A;
        Matrix f;
        f.clear(1,2);
        f.a[0][0]=1;
        f.a[0][1]=1;
        n-=2;
        Matrix s=f*quickPow(mat,n);
        printf("%d\n",(s.a[0][1])%7);
    }
    return 0;
}

HDU 4920 Matrix multiplication

矩阵乘法,直接算会超时。由于是模3,所以0很多,也就是稀疏矩阵。可以优化。

参见下文:http://www.cnblogs.com/jackiesteed/articles/2021604.html

#include<iostream>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<string>
#define LL long long
using namespace std;
int A[805][805],B[805][805];
int C[805][805];
int n;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
            {
                scanf("%d",&A[i][j]);
                A[i][j]%=3;
            }
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
            {
                scanf("%d",&B[i][j]);
                B[i][j]%=3;
            }
        memset(C,0,sizeof(C));
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
            {
                if(A[i][j]==0) continue;
                for(int k=1; k<=n; ++k)
                    C[i][k]+=A[i][j]*B[j][k];
            }
        for(int i=1; i<=n; ++i)
        {
            for(int j=1; j<=n; ++j)
                if(j==1) printf("%d",C[i][j]%3);
                else printf(" %d",C[i][j]%3);
            printf("\n");
        }
    }
    return 0;
}

HDU 1575 Tr A

求矩阵的迹。直接快速幂即可。

#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<set>
#include<string>
#define INF 1000000005
#define LL long long
using namespace std;
const int MAXN =12;
struct Matrix
{
    int n,m;
    int a[MAXN][MAXN];
    void clear(int x=0,int y=0)
    {
        n=x;
        m=y;
        memset(a,0,sizeof(a));
    }
    Matrix operator * (const Matrix &b)const
    {
        Matrix tmp;
        tmp.clear(n,b.m);
        for(int i=0; i<n; ++i)
            for(int j=0; j<b.m; ++j)
            {
                for(int k=0; k<b.m; ++k)
                {
                    if(0==a[i][j]) continue;//优化!
                    tmp.a[i][k]+=a[i][j]*b.a[j][k];
                    tmp.a[i][k]%=9973;
                }
            }
        return tmp;
    }
    void setOne(int x)
    {
        clear(x,x);
        for(int i=0; i<x; ++i)
            a[i][i]=1;
    }
};
Matrix one;
Matrix quickPow(Matrix mat,int n)
{
    Matrix res=one;
    while(n)
    {
        if(n&1) res=res*mat;
        mat=mat*mat;
        n=n>>1;
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        int n,k;
        scanf("%d%d",&n,&k);
        one.setOne(n);
        Matrix mat;
        mat.clear(n,n);
        for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)
            scanf("%d",&mat.a[i][j]);
        mat=quickPow(mat,k);
        int ans=0;
        for(int i=0;i<n;++i)
        {
            ans+=mat.a[i][i];
            ans%=9973;
        }
        printf("%d\n",ans);
    }
    return 0;
}

HDU 1757 A Simple Math Problem

一个简单的递推,建立矩阵后,快速幂。

#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<set>
#include<string>
#define INF 1000000005
#define LL long long
using namespace std;
const int MAXN =12;
int M;
struct Matrix
{
    int n,m;
    int a[MAXN][MAXN];
    void clear(int x=0,int y=0)
    {
        n=x;
        m=y;
        memset(a,0,sizeof(a));
    }
    Matrix operator * (const Matrix &b)const
    {
        Matrix tmp;
        tmp.clear(n,b.m);
        for(int i=0; i<n; ++i)
            for(int j=0; j<b.m; ++j)
            {
                for(int k=0; k<b.m; ++k)
                {
                    if(0==a[i][j]) continue;//优化!
                    tmp.a[i][k]+=a[i][j]*b.a[j][k];
                    tmp.a[i][k]%=M;
                }
            }
        return tmp;
    }
    void setOne(int x)
    {
        clear(x,x);
        for(int i=0; i<x; ++i)
            a[i][i]=1;
    }
};
Matrix one;
Matrix quickPow(Matrix mat,int n)
{
    Matrix res=one;
    while(n)
    {
        if(n&1) res=res*mat;
        mat=mat*mat;
        n=n>>1;
    }
    return res;
}
int main()
{
    int k;
    one.setOne(10);
    while(scanf("%d%d",&k,&M)!=EOF)
    {
        Matrix mat;
        mat.clear(10,10);
        for(int i=0; i<9; ++i)
            mat.a[i+1][i]=1;
        for(int i=0; i<10; ++i)
            scanf("%d",&mat.a[9-i][9]);
        if(k<10) printf("%d\n",k%M);
        else
        {
            Matrix f;
            f.clear(1,10);
            for(int i=0; i<10; ++i)
                f.a[0][i]=i;
            k-=9;
            f=f*quickPow(mat,k);
            printf("%d\n",f.a[0][9]);
        }
    }
    return 0;
}

UVa 10870  Recurrences

与上面类型相似的题,建立矩阵,再快速幂加速。注意会超int。

#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<set>
#include<string>
#define INF 1000000005
#define LL long long
using namespace std;
const int MAXN =20;
int M;
struct Matrix
{
    int n,m;
    LL a[MAXN][MAXN];
    void clear(int x=0,int y=0)
    {
        n=x;
        m=y;
        memset(a,0,sizeof(a));
    }
    Matrix operator * (const Matrix &b)const
    {
        Matrix tmp;
        tmp.clear(n,b.m);
        for(int i=0; i<n; ++i)
            for(int j=0; j<b.m; ++j)
            {
                for(int k=0; k<b.m; ++k)
                {
                    if(0==a[i][j]) continue;//优化!
                    tmp.a[i][k]+=a[i][j]*b.a[j][k];
                    tmp.a[i][k]%=M;
                }
            }
        return tmp;
    }
    void setOne(int x)
    {
        clear(x,x);
        for(int i=0; i<x; ++i)
            a[i][i]=1;
    }
};
Matrix one;
Matrix quickPow(Matrix mat,LL n)
{
    Matrix res=one;
    while(n)
    {
        if(n&1) res=res*mat;
        mat=mat*mat;
        n=n>>1;
    }
    return res;
}
int main()
{
    int d,n;
    while(scanf("%d%d%d",&d,&n,&M)!=EOF)
    {
        if(!d&&!n&&!M) break;
        one.setOne(d);
        Matrix mat;
        mat.clear(d,d);
        for(int i=0; i<d; ++i)
            mat.a[i+1][i]=1;
        for(int i=0; i<d; ++i)
            scanf("%lld",&mat.a[d-1-i][d-1]);
        Matrix f;
        f.clear(1,d);
        for(int i=0; i<d; ++i)
            scanf("%lld",&f.a[0][i]);
        if(n<=d)
            printf("%lld\n",f.a[0][n-1]%M);
        else
        {
            n-=d;
            f=f*quickPow(mat,n);
            printf("%lld\n",f.a[0][d-1]%M);
        }
    }
    return 0;
}

POJ 3734 Blocks

递推+矩阵快速幂。

设计状态的时候要考虑所有可能的情况,保证无重复无遗漏,再考虑转移。最后用矩阵加速。

#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<set>
#include<string>
#define INF 1000000005
#define LL long long
using namespace std;
const int MAXN =4;
int M=10007;
struct Matrix
{
    int n,m;
    int a[MAXN][MAXN];
    Matrix(int x=0,int y=0):n(x),m(y)
    {
        memset(a,0,sizeof(a));
    }
    void clear(int x=0,int y=0)
    {
        n=x;
        m=y;
        memset(a,0,sizeof(a));
    }
    Matrix operator * (const Matrix &b)const
    {
        Matrix tmp;
        tmp.clear(n,b.m);
        for(int i=0; i<n; ++i)
            for(int j=0; j<b.m; ++j)
            {
                for(int k=0; k<b.m; ++k)
                {
                    if(0==a[i][j]) continue;//ÓÅ»¯£¡
                    tmp.a[i][k]+=a[i][j]*b.a[j][k];
                    tmp.a[i][k]%=M;
                }
            }
        return tmp;
    }
    void setOne(int x)
    {
        clear(x,x);
        for(int i=0; i<x; ++i)
            a[i][i]=1;
    }
};
Matrix one;
Matrix quickPow(Matrix mat,int n)
{
    Matrix res=one;
    while(n)
    {
        if(n&1) res=res*mat;
        mat=mat*mat;
        n=n>>1;
    }
    return res;
}
int main()
{
    one.setOne(3);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        Matrix mat(3,3);
        mat.a[0][0]=2,mat.a[0][1]=1,mat.a[0][2]=0;
        mat.a[1][0]=2,mat.a[1][1]=2,mat.a[1][2]=2;
        mat.a[2][0]=0,mat.a[2][1]=1,mat.a[2][2]=2;
        Matrix f(3,1);
        f.a[0][0]=1;
        Matrix ans=f*quickPow(mat,n);
        printf("%d\n",ans.a[0][0]);
    }
    return 0;
}

ACM 矩阵题目整理

时间: 2024-10-15 12:44:36

ACM 矩阵题目整理的相关文章

ACM 字符串 题目整理

AC自动机 UVa 11468  Substring AC自动机+概率DP. 注意要补全不存在的边. 为什么要补全不存在的边呢?补全以后可以直接找到状态的转移,即从所有子节点就可以实现所有状态转移. #include<iostream> #include<vector> #include<cmath> #include<map> #include<algorithm> #include<cstring> #include<cst

ACM 暴力搜索题 题目整理

UVa 129 Krypton Factor 注意输出格式,比较坑爹. 每次要进行处理去掉容易的串,统计困难串的个数. #include<iostream> #include<vector> #include<cmath> #include<map> #include<algorithm> #include<cstring> #include<cstdio> #include<cstdlib> #include

ACM学习资料整理

ACM学习资料整理 声明:参考泥瓦匠BYSocket.POJ题目分类推荐 (很好很有层次感)整理所得 1 推荐题库 ?http://ace.delos.com/usaco/ 美国的OI 题库,如果是刚入门的新手,可以尝试先把它刷通,能够学到几乎全部的基础算法极其优化,全部的题解及标程还有题目翻译可以baidu 一个叫NOCOW 的网站.   ?http://livearchive.onlinejudge.org/ 上面有全部的赛区真题,绝大部分都可以提交,不适合当题库刷,不过在这里找题非常方便.

数据库题目整理及详解(四)

前言 有多少次挥汗如雨,伤痛曾添满记忆,只因为始终相信,去拼搏才能胜利.总在鼓舞自己,要成功就得努力.热血在赛场沸腾,巨人在赛场升起. 相信自己,你将赢得胜利,创造奇迹:相信自己,梦想在你手中,这是你的天地.当一切过去,你们将是第一. 相信自己,你们将超越极限,超越自己! 相信自己,加油吧,健儿们,相信你自己. 坐在中体对面, 听着这振奋激昂的加油欢呼声, 照样可以感受到校运会的气势磅礴, 虽然我还在敲代码-- 来个这个吧, 特殊纪念, 沃夫慈悲: 说明 老生常谈! 接着之前的SQL语句继续整理

【Android进阶】Android面试题目整理与讲解

这一篇文章专门整理一下研究过的Android面试题,内容会随着学习不断的增加,如果答案有错误,希望大家可以指正 1.简述Activity的生命周期 当Activity开始启动的时候,首先调用onCreate(),onStart(),onResume()方法,此时Activity对用户来说,是可见的状态 当Activity从可见状态变为被Dialog遮挡的状态的时候,会调用onPause()方法,此时的Activity对用户可见,但是不能相 应用户的点击事件 当Activity从可见状态变为被其他

博弈论 题目整理

博弈论里面一个非常重要的结论: 如果前一个状态所有可能都是必败态,那么当前状态一定是必胜态. 如果前一个状态所有可能有一个是必胜态,那么当前状态一定是必败态. POJ 2484 A Funny Game 博弈游戏里面后手经常占据优势.除了A可以一次性全部拿光的情况,其他时候B都可以采取与A相同的策略,这样每次将石子分为相同的两组,最后获胜的一定是B. #include <cstdio> #include <cstring> #include <algorithm> us

【Android进阶】Android面试题目整理与讲解(二)

今天真机调试的时候莫名其妙遇到了这样的一个问题: This product type must be built using a provisioning profile, however no provisioning profile matching both the identity "iPhone Developer" and the bundle identifier..... 具体如下图所示: 十分蛋疼, 发现不管是从网上下的demo, 还是自己的过程.凡事真机测试的时候都

【Java基础】Java面试题目整理与解说(二)

1.Collection 和 Collections 的差别. Collection 是集合类的上级接口,继承于他的接口主要有 Set 和 List. Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索.排序.线程安全化等操作. 2.HashMap 和 Hashtable 的差别. HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完毕了 Map 接口,HashMap是非线程安全,效率上可能高于 Hashtable.在多个线程

【Android进阶】Android面试题目整理与讲解(一)

这一篇文章专门整理一下研究过的Android面试题,内容会随着学习不断的增加,如果答案有错误,希望大家可以指正 1.简述Activity的生命周期 当Activity开始启动的时候,首先调用onCreate(),onStart(),onResume()方法,此时Activity对用户来说,是可见的状态 当Activity从可见状态变为被Dialog遮挡的状态的时候,会调用onPause()方法,此时的Activity对用户可见,但是不能相 应用户的点击事件 当Activity从可见状态变为被其他