矩阵快速幂小结&反思 不断补充ing

14 篇文章 0 订阅
11 篇文章 0 订阅

等整理完网络流的题目,再整理矩阵的,此坑待填

 

====================

 

poj3233 Matrix Power Series

 

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

#define FD "%d"
#define FLL "%lld"

int matsz,mod;
const int N=70;

struct matrix
{
    int mat[N][N];
    matrix(int v)
    {
        memset(mat,0,sizeof(mat));
        for(int i=0;i<matsz;i++)
        mat[i][i]=v;
    }
    matrix operator *(matrix b)
    {
        matrix tmp(0);
        for(int i=0;i<matsz;i++)
        for(int k=0;k<matsz;k++)
        if(mat[i][k])
        {
          for(int j=0;j<matsz;j++)
          {
              tmp.mat[i][j]+=mat[i][k]*b.mat[k][j];
              tmp.mat[i][j]%=mod;
          }
        }
        return tmp;
    }
    void print()
    {
        for(int i=0;i<matsz;i++)
            for(int j=0;j<matsz;j++)
            printf(j==matsz-1?"%d\n":"%d ",mat[i][j]);
    }
};

matrix qpow(matrix t,int k)
{
    matrix ret(1);
    while(k)
    {
        if(k&1)
        ret=ret*t;
        t=t*t;
        k>>=1;
    }
    return ret;
}

int main()
{
    int n,k,m;
    while(~scanf("%d%d%d",&n,&k,&m))
    {
        matsz=n<<1;
        mod=m;
        matrix t(0);
        for(int i=0;i<n;i++)
        t.mat[i][i]=t.mat[i][i+n]=1;

        for(int i=n;i<matsz;i++)
        for(int j=n;j<matsz;j++)
        scanf("%d",&t.mat[i][j]);

        matrix ret=qpow(t,k+1);
        int ans;
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        t.mat[i][j]=t.mat[i+n][j+n];
        for(int i=n;i<matsz;i++)
        for(int j=0;j<n;j++)
        t.mat[i][j]=t.mat[i][j+n]*t.mat[i][j+n]%mod;

        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            if(i==j)ret.mat[i][j+n] = (ret.mat[i][j+n]-1+mod)%mod;
            printf(j==n-1?"%d\n":"%d ",ret.mat[i][j+n]);
        }
    }
    return 0;
}

 

 

 

 

 

 

loj1006  Hex-a-bonacci

 

题意:

          给出递推公式,求第n项。

做法:

         构造矩阵,然后快速幂。

 

#include <iostream>
#include <cstdio>
#include <cstring>
 
using namespace std;
const int Mod=10000007;
int a, b, c, d, e, f;
int fn( int n ) {
    if( n == 0 ) return a;
    if( n == 1 ) return b;
    if( n == 2 ) return c;
    if( n == 3 ) return d;
    if( n == 4 ) return e;
    if( n == 5 ) return f;
    return( fn(n-1) + fn(n-2) + fn(n-3) + fn(n-4) + fn(n-5) + fn(n-6) );
}
const int N=6;
struct matrix
{
   long long mat[N][N];
   matrix(){memset(mat,0,sizeof(mat));for(int i=0;i<N;i++)mat[0][i]=1;for(int i=1;i<N;i++)mat[i][i-1]=1;}
   matrix(int n){memset(mat,0,sizeof(mat));for(int i=0;i<N;i++)mat[i][i]=1;}
   void print(){for(int i=0;i<N;i++){for(int j=0;j<N;j++)cout<<mat[i][j]<<" ";printf("\n"); } }
   matrix operator *(matrix a)
   {
       matrix ret;
       for(int i=0;i<N;i++)
       for(int j=0;j<N;j++)
       {
           ret.mat[i][j]=0;
           for(int k=0;k<N;k++)
           ret.mat[i][j]+=mat[i][k]*a.mat[k][j];
           ret.mat[i][j]%=Mod;
       }
       return ret;
   }
};
 
int solve(int n)
{
    int ret=0;
    matrix a,t(n);
 
    n-=5;
    while(n)
    {
        if(n&1)
        t=t*a;
        a=a*a;
        n>>=1;
    }
    for(int i=0;i<N;i++)
    ret=(ret+t.mat[0][i]*fn(5-i))%Mod;
    return ret;
}
 
int main() {
//    freopen("in","r",stdin);
    int n, caseno = 0, cases,ret;
    scanf("%d", &cases);
    while( cases-- ) {
        scanf("%d %d %d %d %d %d %d", &a, &b, &c, &d, &e, &f, &n);
        if(n<=5)
        ret=fn(n);
        else
        ret=solve(n);
        printf("Case %d: %d\n", ++caseno,ret % 10000007);
    }
    return 0;
}

 

 

 

 

 

 

hdu4686 Arc of Dream(2013多校题目)

题意:

          给出递推公式,求第n项。

做法:

         构造矩阵,然后快速幂。

反思:

          注意及时取模,赋值不要写错了。

 

#include <cstdio>
#include <cstring>

using namespace std;

typedef long long LL;
#define FLL "%I64d"
const LL Mod=1e9+7;
const int Maxn=7;
struct martix
{
    LL mat[Maxn][Maxn];
    martix()
    {
        memset(mat,0,sizeof(mat));
    }
    martix(int a)
    {
        memset(mat,0,sizeof(mat));
        for(int i=0; i<Maxn; i++)mat[i][i]=1;
    }
    void operator *=(const martix &a)
    {
        martix tmp;
        for(int i=0; i<Maxn; i++)
          for(int k=0; k<Maxn; k++)
            if(mat[i][k])
            for(int j=0; j<Maxn; j++)
                {
                    tmp.mat[i][j]+=(mat[i][k]*a.mat[k][j])%Mod;
                    tmp.mat[i][j]%=Mod;
                }


        for(int i=0; i<Maxn; i++)
            for(int j=0; j<Maxn; j++)
                mat[i][j]=tmp.mat[i][j];
    }
};

martix qpow(martix a,LL n)
{
    martix ret(1);
    while(n)
    {
        if(n&1)
        ret*=a;
        a*=a;
        n>>=1;
    }
    return ret;
}

int main()
{
    LL n,a0,ax,ay,b0,bx,by,s1;

    while(~scanf(FLL,&n))
    {
        scanf(FLL FLL FLL FLL FLL FLL,&a0,&ax,&ay,&b0,&bx,&by);
        if(!n)
        {
            puts("0");
            continue;
        }
        s1=a0*b0%Mod;
        if(n==1)
        {
            printf(FLL,s1);
            puts("");
            continue;
        }

        martix ret;
        ret.mat[0][0]=ret.mat[0][1]=1;
        ret.mat[1][1]=ax*bx%Mod;
        ret.mat[1][2]=ax*by%Mod;
        ret.mat[1][3]=ay*bx%Mod;
        ret.mat[1][4]=1;

        ret.mat[2][2]=ax;
        ret.mat[2][5]=1;//!!!

        ret.mat[3][3]=bx;
        ret.mat[3][6]=ret.mat[4][4]=ret.mat[5][5]=ret.mat[6][6]=1;

        ret=qpow(ret,n-1);
        LL ans=0,a1,b1;
        a1=(a0%Mod*ax%Mod+ay)%Mod;
        b1=(b0%Mod*bx%Mod+by)%Mod;
        LL tmp[Maxn]={s1,a1*b1%Mod,a1,b1,ay*by%Mod,ay,by};
        for(int i=0;i<Maxn;i++)
        {
            ans+=(tmp[i]*ret.mat[0][i])%Mod;
            ans%=Mod;
        }
        printf(FLL,ans);
        puts("");
    }
    return 0;
}

 

 

 

 

 

 

 

poj3735 Training little cats

题意:

          给出n个数,一开始都是0。

          有三种操作:g i:第i个数加一;e i:第i个数变成0;s i j:第i和第j个数交换。

          每次给你k个操作,然后重复这k个操作m次,求最后n个数分别是多少。

做法:

           把三种操作用矩阵乘法来表示

反思:

           没用long long wa了一次。

 

 

#include <cstdio>
#include <cstring>

using namespace std;

#define SET(a,x) memset(a,x,sizeof(a))
#define RE(i,n) for(long long i = 1; i <= n; i++)
#define _RE(i,n) for(long long i = 0; i <= n; i++)

long long n,m,k;
const long long MAX = 110;

struct martix {
    long long mat[MAX][MAX];
    long long a,b;
    martix(long long f=0) {
        SET(mat,0);
        _RE(i,n)mat[i][i]=f;
    }
    void operator *= (martix t) {
        martix ret;
        _RE(i,n)
        _RE(k,n)if(mat[i][k])
            _RE(j,n) {
            ret.mat[i][j] += mat[i][k] * t.mat[k][j];
//              ret.mat[i][j] %= MOD;
        }
        _RE(i,n)
        _RE(j,n)
        mat[i][j] = ret.mat[i][j];
    }
    void dis(){
    _RE(i,n){
        _RE(j,n)
        printf("%I64d ",mat[i][j]);
        puts("");
    }

    }
};

martix qpow(martix ret,long long m){
    martix ans(1);
   while(m){
    if(m & 1)
    ans *= ret;
    ret *= ret;
    m >>= 1;
   }
    return ans;
}

int main() {
    while(scanf("%I64d%I64d%I64d",&n,&m,&k),n||m||k) {
        char op[5];
        long long x,y;
        martix ret(1);
        while(k--) {

            scanf("%s%I64d",op,&x);
            martix cur(1);
            if(op[0] == 'g') {
                cur.mat[x][0] = 1;
            } else if(op[0] == 'e') {
                cur.mat[x][x] = 0;
            } else if(op[0] == 's') {
                scanf("%I64d",&y);
                cur.mat[x][x] = cur.mat[y][y] = 0;
                cur.mat[x][y] = cur.mat[y][x] = 1;
            }
            cur *=  ret;
            ret = cur;
        }
       if(m == 0){
        RE(i,n)
        printf(i == n?"0\n":"0 ");
        continue;
       }
       ret = qpow(ret,m);
        RE(i,n) {
            printf(i == n?"%I64d\n":"%I64d ",ret.mat[i][0]);
        }
    }
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值