矩阵练习

来源:互联网 发布:php中连接符 编辑:程序博客网 时间:2024/06/01 18:32

HDU4549  M斐波那契数列(矩阵快速幂+欧拉定理)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4549

中文题目读起来就是爽啊,常规做了一遍,妥妥超时了,看那个a,b的指数满足斐波那契数列,所以用矩阵来构造。然后在WA了很多遍找不到错误的情况下,后来看了下网上的题解,才知道在做矩阵乘法的时候即使用long long也有可能溢出~题目要求对10000000007取模,是个质数。A^B%C,且C为质数,A,C互质,利用数论的知识可以得到:

A^B%C=A^(B%(C-1))%C;


代码:

<span style="font-family:FangSong_GB2312;font-size:18px;">#include <stdio.h>#include <string.h>#define mod 1000000007#define Max_dimension 2typedef long long LL;typedef LL Matrix[Max_dimension][Max_dimension];int ndim=Max_dimension;Matrix A={{1,1},{1,0}};void m_zero(Matrix x){    memset(x,0,sizeof(LL)*Max_dimension*Max_dimension);}void m_one(Matrix x){    m_zero(x);    for(int i=0;i<ndim;i++)        x[i][i]=1;}void m_copy(Matrix src,Matrix dest){    memcpy(dest,src,sizeof(LL)*Max_dimension*Max_dimension);}void m_multiple(Matrix a,Matrix b,Matrix c){    for(int i=0;i<ndim;i++)        for(int j=0;j<ndim;j++)    {        c[i][j]=0;        for(int k=0;k<ndim;k++)        {            c[i][j]+=(a[i][k]*b[k][j])%(mod-1);            c[i][j]%(mod-1);        }    }}void m_pow(Matrix x,int m,Matrix y){    Matrix temp,temp_x;    m_one(y);m_copy(x,temp_x);    while(m)    {        if(m&1)        {            m_multiple(temp_x,y,temp);            m_copy(temp,y);        }        if(m>>=1)        {            m_multiple(temp_x,temp_x,temp);            m_copy(temp,temp_x);        }    }}LL quick_pow(LL t,LL m){    LL tmp=t%mod;    LL ant=1;    while(m)    {        if(m&1)        {            ant*=tmp;            ant%=mod;        }        m>>=1;        tmp*=tmp;        tmp%=mod;    }    return ant;}//Matrix B={{1},{2}};int main(){    //freopen("in.txt","r",stdin);         int a,b,n;    Matrix ans;    while(scanf("%d%d%d",&a,&b,&n)!=EOF)    {m_zero(ans);        if(n)            m_pow(A,n-1,ans);        else        {            ans[0][0]=0;            ans[1][0]=1;        }        //m_multiple(ans,B,res); //b的次幂        LL num1=quick_pow(b,ans[0][0])%mod;        LL num2=quick_pow(a,ans[1][0])%mod;        printf("%d\n",num1*num2%mod);    }    return 0;}/*100 10 310 10 5*/</span>


HDU2254 奥运

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2254

如果能够想到用矩阵的话,这道题目就不难做,求两个城市之间的走法,在限制时间内达到,矩阵幂之和即可·····用STL的map来保存每个点·····

代码:

<span style="font-family:FangSong_GB2312;font-size:18px;">#include <stdio.h>#include <string.h>#include <algorithm>#include <map>using namespace std;#define mod 2008#define size 30int ndim;struct Matrix{    int a[size][size];}tem;Matrix m_one(Matrix x){    for(int i=0;i<30;i++)        for(int j=0;j<30;j++)            if(i==j)                x.a[i][j]=1;            else                x.a[i][j]=0;    return x;}Matrix m_add(Matrix a,Matrix b){    Matrix c;    for(int i=0;i<ndim;i++)        for(int j=0;j<ndim;j++)        {            c.a[i][j]=(a.a[i][j]+(_int64)b.a[i][j])%mod;            c.a[i][j]%=mod;        }        return c;}Matrix m_multiple(Matrix a,Matrix b){    Matrix c;    for(int i=0;i<ndim;i++)        for(int j=0;j<ndim;j++)        {            c.a[i][j]=0;            for(int k=0;k<ndim;k++)            {                c.a[i][j]+=(a.a[i][k]*(_int64)b.a[k][j])%mod;                c.a[i][j]%=mod;            }        }        return c;}Matrix m_pow(Matrix x,int m){    Matrix temp;    temp=x;    x=m_one(x);    while(m)    {        if(m&1)            x=m_multiple(x,temp);        temp=m_multiple(temp,temp);        m>>=1;    }    return x;}Matrix m_pow_sum(Matrix x,int p){    //Matrix tem;    if(p==1)        return x;    else if(p&1)        return m_add(m_pow(x,p),m_pow_sum(x,p-1));    else        return m_multiple(m_pow_sum(x,p>>1),m_add(m_pow(x,p>>1),tem));}int main(){    int T,n,k,t1,t2,v1,v2;    int x,y,num;    map<int,int> mapp;    Matrix res,s1,s2;    tem=m_one(tem);    while(scanf("%d",&T)!=EOF)    {        for(int i=0;i<30;i++)            for(int j=0;j<30;j++)                res.a[i][j]=0;        num=0;        mapp.clear();        while(T--)        {            scanf("%d%d",&x,&y);            if(!mapp.count(x))                mapp[x]=num++;            if(!mapp.count(y))                mapp[y]=num++;            res.a[mapp[x]][mapp[y]]++;  //记录这两点之间有几种走法        }        ndim=num;        scanf("%d",&k);        while(k--)        {            scanf("%d%d%d%d",&v1,&v2,&t1,&t2);                      if(t2<t1|| mapp.count(v1)==0 || mapp.count(v2)==0 )            {                printf("0\n");                continue;            }          int p1=0,p2=0;          Matrix r=res;          if(t1>1)          {              s1=m_pow_sum(r,t1-1);              p1=s1.a[mapp[v1]][mapp[v2]];          }          if(t2>=1)          {              s2=m_pow_sum(r,t2);              p2=s2.a[mapp[v1]][mapp[v2]];          }          printf("%d\n",(p2-p1+mod)%mod);        }    }    return 0;}</span>

HDU2604 Queuing

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2604

题意:用m和f来随机排列,但是不可以出现fmf和fff的形式,问有多少种方式

分析:f(n)表示n个人的排列方法···这样考虑:

如果前边的人都符合题意,那么f(n)就是f(n-1)在增添一个人,但是不能出现那两种形式。想象f(n-1)是合法的,再增添一个m是合法的,有f(n-1)种····

但是如果最后一个人是m,则f(n-1)可以是f或者m结尾,则要看f(n-2),但是这ff和mf都不能直接确定是不是合法,再向前看一个,即f(n-3),就有4种形式了,mm,mf,fm,ff分别和f组合,fm,ff显然不合法,去掉。mmf无限制,f(n-3)种···

还剩一个mf,仅看f(n-3)是无法看出能不能放,再向前看一个,即f(n-4),mmff是无限制的,所以f(n-4)种

综上:f(n)=f(n-1)+f(n-3)+f(n-4)

置于矩阵呢,很好构造,

 A={{1,0,1,1},{1,0,0,0},{0,1,0,0,},{0,0,1,0}}
代码:
<span style="font-family:FangSong_GB2312;font-size:18px;">#include <stdio.h>#include <string.h>#include <stdlib.h>#define Max_dimension 4//#define mod 2008typedef int Matrix_type;typedef long long  Max_int_type;typedef Matrix_type Matrix[Max_dimension][Max_dimension];int mod;int ndim=Max_dimension;void m_zero(Matrix x){    memset(x,0,sizeof(Matrix_type)*Max_dimension*Max_dimension);}void m_one(Matrix x){    m_zero(x);    for(int i=0;i<ndim;i++)        x[i][i]=1;}void m_copy(Matrix src,Matrix dest){    memcpy(dest,src,sizeof(Matrix_type)*Max_dimension*Max_dimension);}//c=a*bvoid m_multiple(Matrix  a,Matrix b,Matrix c){    int i,j,k;    for(i=0;i<ndim;i++)        for(j=0;j<ndim;j++)        {             c[i][j]=0;            if(mod<=1)                for(k=0;k<ndim;k++)         c[i][j]+=a[i][k]*b[k][j];            else                for(k=0;k<ndim;k++)    {        c[i][j]+=(a[i][k]*(Max_int_type)b[k][j])%mod;                    c[i][j]%=mod;                }        }}//y=x^nvoid m_pow(Matrix x, unsigned int n, Matrix y){    Matrix temp,temp_x;    m_one(y);    m_copy(x,temp_x);    while(n)    {        if (n&1)        {            m_multiple(temp_x,y,temp);            m_copy(temp,y);        }        if (n >>= 1)        {            m_multiple(temp_x,temp_x,temp);            m_copy(temp,temp_x);        }    }}Matrix A={{1,0,1,1},{1,0,0,0},{0,1,0,0,},{0,0,1,0}};Matrix B={{9},{6},{4},{2}};int main(){     //freopen("in.txt","r",stdin);     Matrix ans,sum;     int l;     while(scanf("%d%d",&l,&mod)!=EOF)     {           if(l==0)           {            printf("0\n");            continue;           }           if(l==1)           {                 printf("%d\n",2%mod);                 continue;           }           if(l==2)           {                 printf("%d\n",4%mod);                 continue;           }           if(l==3)           {                 printf("%d\n",6%mod);                 continue;           }           if(l==4)           {                 printf("%d\n",9%mod);                 continue;           }           m_pow(A,l-4,ans);           m_multiple(ans,B,sum);           printf("%d\n",sum[0][0]%mod);     }     return 0;}</span>



      

0 0
原创粉丝点击