『专题』十个利用矩阵乘法解决的经典题目(转)

转载声明:http://www.cnblogs.com/kuangbin/archive/2012/08/17/2643347.html
(没找到原址,转了kuangbin巨巨的保留而用)

个人感想:最近在敲10道经典矩阵题目,我搞了前9道,最后一道看似看懂了,但也没搞出来,贴下一战绩吧,感觉很有用处.

poj3233

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }


ll N,m,k;

struct mat
{
     ll g[35][35];
     void Clear()
     {
         memset(g,0,sizeof(g));
     }

};

mat mul(mat A,mat B)
{
    mat C;
    C.Clear();
    for(int i=0;i<N;i++)
    {
        for(int k=0;k<N;k++)
        {
            for(int j=0;j<N;j++)
            {
                C.g[i][j]=(C.g[i][j]+A.g[i][k]*B.g[k][j])%m;
            }
        }
    }
    return C;
}
mat cal(mat A,mat B)
{
    mat C;
    C.Clear();

    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            C.g[i][j]=(A.g[i][j]+B.g[i][j])%m;
        }
    }

    return C;
}
mat pow(mat A,ll n)
{
    mat B;
    B.Clear();
    for(int i=0;i<N;i++)
    {
        B.g[i][i]=1;
    }

    while(n>0)
    {
        if(n&1) B=mul(B,A);
        A=mul(A,A);
        n>>=1;
    }
    return B;
}
mat deal(mat x,ll k)
{

    if(k==1) return x;

    mat B=pow(x,(k+1)/2);


    mat T=deal(x,k/2);



    if(k%2==0) return cal(T,mul(B,T));//exp: s(6) = (1 + A^3) * s(3)
    return cal(x,mul(cal(x,B),T));//exp: s(7) = A + (A + A^4) * s(3)
}
void solve()
{
    mat A;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            scanf("%I64d",&A.g[i][j]);
        }
    }




    mat P=deal(A,k);

    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(j==0)printf("%I64d",P.g[i][j]);
            else printf(" %I64d",P.g[i][j]);
        }
        printf("\n");
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif
    while(scanf("%I64d%I64d%I64d",&N,&k,&m)!=EOF)
    {
        solve();
    }

    return 0;
}

hdu 2254 奥运

#include <stdio.h>
#include <string.h>
#include <cmath>

#define maxn 30
const int MOD = 2008;
int len;
__int64 city[maxn];
struct Mat
{
    int mat[maxn][maxn];
}e,init;
int FindCity(__int64 x,bool flag)
{
    int i;
    for (i=0;i<len;i++)
        if(city[i]==x)
            return i;
    if (flag)
    {
        city[len++] = x;
        return len-1;
    }
    return 50;/*没找到城市*/
}
Mat operator+(Mat a,Mat b)
{
    Mat c;
    int i,j;
    for (i=0;i<len;i++)
    {
        for(j=0;j<len;j++)
            c.mat[i][j] = (a.mat[i][j]+b.mat[i][j])%MOD;
    }
    return c;
}
Mat operator*(Mat a,Mat b)
{
    int i,j,k;
    Mat c;
    for (i=0;i<len;i++)
    {
        for (j=0;j<len;j++)
        {
            c.mat[i][j] = 0;
            for(k=0;k<len;k++)
                c.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%MOD;
        }
    }
    return c;
}
Mat operator^(Mat a,int x)
{
    Mat p = e,q = a;
    while (x)
    {
        if(x&1)
            p = p*q;
        x>>=1;
        q = q*q;
    }
    return p;
}

Mat solve(Mat x,int k)
{

    if(k==1) return x;

    Mat B=x^((k+1)/2);


    Mat T=solve(x,k/2);



    //if(k%2==0) return cal(T,mul(B,T));//exp: s(6) = (1 + A^3) * s(3)
    if(k%2==0) return T+(B*T);
    //return cal(x,mul(cal(x,B),T));//exp: s(7) = A + (A + A^4) * s(3)
    return x+((x+B)*T);
}
int main()
{
    __int64 v1,v2;
    int t1,t2,i,j,n,k,c,locate1,locate2,sum;
    Mat tem1,tem2;
    for(i=0;i<maxn;i++)
        for(j=0;j<maxn;j++)
            e.mat[i][j] = (i==j);
    while (scanf("%d",&n)!=EOF)
    {
        len = 0;
        memset(&init,0,sizeof(init));
        while (n--)
        {
            scanf("%I64d%I64d",&v1,&v2);
            locate1 = FindCity(v1,1);
            locate2 = FindCity(v2,1);
            init.mat[locate1][locate2]++;
        }
        scanf("%d",&k);
        while (k--)
        {
            scanf("%I64d%I64d%d%d",&v1,&v2,&t1,&t2);
            if(t1>t2)
            {
                int temp=t1;
                t1=t2;
                t2=temp;
            }

            locate1 = FindCity(v1,0);
            locate2 = FindCity(v2,0);
            if(locate1==50||locate2==50||(t1==0&&t2==0))
                printf("0\n");
            else
            {
                if (t1>1)
                {
                    tem1 = solve(init,t2);
                    tem2 = solve(init,t1-1);
                    sum = (tem1.mat[locate1][locate2]%MOD-tem2.mat[locate1][locate2]%MOD)%MOD;
                }
                else
                {
                    tem1 = solve(init,t2);
                    sum = tem1.mat[locate1][locate2]%MOD;
                }
                if(sum<0)
                    sum+=MOD;
                printf("%d\n",sum);
            }
        }
    }
    return 0;
}

vijosP1067 守望者的烦恼:

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
const long long mod=7777777;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }

 typedef vector<ll>vec;
 typedef vector<vec>mat;
 ll K,N;
 mat mul(mat &A,mat & B)
 {
     mat C(A.size(),vec(B[0].size()));

     for(int i=0;i<A.size();i++)
     {
         for(int k=0;k<B.size();k++)
         {
             for(int j=0;j<B[0].size();j++)
             {
                 C[i][j]=(C[i][j]+A[i][k]*B[k][j])%mod;
             }
         }
     }
     return C;
 }
 mat pow(mat A,ll n)
 {
     mat B(A.size(),vec(A.size()));

     for(int i=0;i<A.size();i++)
     {
         B[i][i]=1;
     }
     while(n>0)
     {
         if(n&1) B=mul(B,A);
         A=mul(A,A);
         n>>=1;
     }
     return B;
 }
 void solve()
 {
     mat A(K,vec(K));
     for(int i=0;i<K;i++)
     {
         A[0][i]=1;
     }
     for(int i=1;i<K;i++)
     {
         A[i][i-1]=1;
     }

     A=pow(A,N);

     mat B(K,vec(K));
     B[0][0]=1;

     A=mul(A,B);

     cout<<A[0][0]<<endl;

 }
int main()
{

    while(cin>>K>>N)
    {
        solve();
    }
    return 0;
}

vijosP1049 送给圣诞夜的礼物(m次置换)

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }

 int N,m,k;

 int G[15][105];
 class mat
 {
public:
     int g[105][105];
     void Clear()
     {
         memset(g,0,sizeof(g));
     }
 };
 mat mul(mat A,mat B)
 {
     mat C;
     C.Clear();


     for(int i=0;i<N;i++)
     {
         for(int k=0;k<N;k++)
         {
             for(int j=0;j<N;j++)
             {
                 C.g[i][j]=(C.g[i][j]+A.g[i][k]*B.g[k][j]);
             }
         }
     }
     return C;
 }
 mat pow(mat A,ll n)
 {
     mat B;
     B.Clear();

     for(int i=0;i<N;i++)
     {
         B.g[i][i]=1;
     }
     while(n>0)
     {
         if(n&1) B=mul(B,A);
         A=mul(A,A);
         n>>=1;
     }
     return B;
 }

 void solve()
 {
     int t=k/m;

     mat A;
     A.Clear();

     for(int j=0;j<N;j++)
     {
         A.g[j][G[m][j+1]-1]=1;

        // cout<<G[m][j+1]<<endl;
     }

     A=pow(A,t);






     int l=k%m;//最后的转换

     if(l)
     {
         mat B;
         B.Clear();

         for(int j=0;j<N;j++)
         {
            B.g[j][ G[l][j+1]-1 ]=1;
         }

         A=mul(B,A);
     }


     //ans----->
     mat C;
     C.Clear();

     for(int j=0;j<N;j++)
     {
         C.g[j][0]=j+1;
     }




     A=mul(A,C);

//     cout<<"------->"<<endl;
//     for(int i=0;i<N;i++)
//     {
//         for(int j=0;j<N;j++)
//         {
//             printf("%d ",A.g[i][j]);
//         }
//         printf("\n");
//     }

     for(int j=0;j<N;j++)
     {
         if(j==0)printf("%d",A.g[j][0]);
         else printf(" %d",A.g[j][0]);
     }
     printf("\n");
 }

int main()
{


    while(scanf("%d%d%d",&N,&m,&k)!=EOF)
    {
          memset(G,0,sizeof(G));
          for(int j=1;j<=N;j++)
          {
             G[0][j]=j;
          }

          int x;
          for(int i=1;i<=m;i++)
          {
              for(int j=1;j<=N;j++)
              {
                  scanf("%d",&x);
                  G[i][j]=G[i-1][x];
              }
          }
          solve();
    }

    return 0;
}

ps:多米诺骨牌的判断疑问
1.((~i)&j) == ((~i)&(SIZE-1))
对于第n-1列,那么我们就 例如 (从左往右看 转成从上往下看){001} -反码代表第n层状态{110} 因为只能打横铺不能打竖,否则就冲突,就判断j这个状态存不存在(110)这个状态.
2. for (int k=0; k<8; k++)isValid=isValid||(i&j)==validSet[k];
我们可以发现kuangbin巨巨写的const int validSet[]={0,3,6,12,15,24,27,30};两个两个1在移动为什么需要那么判呢,主要是判断是否可以放一个打竖的多米诺骨牌,这样的状态是允许的,因为是为了防止状态重复计算,而把打竖的抽离出来再这样判. 然后建图即可.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值