HDU 1757,1575,2604,2256 矩阵快速幂总结

HDU 1757:

就是由f(x)可以得出矩阵……可以得到下面的a0到a9并上有1,0的矩阵,与f0到f9相乘一次可以得到f1到f10,所以^(k-9)次就可以得到fn-9到fn了,第一行就是f(k)……


这个图来自:http://www.cnblogs.com/wally/archive/2013/03/01/2938305.html

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 10000005
#define MN 3005
//#define INF 1000000007
#define eps 1e-7
using namespace std;
typedef long long ll;
#define Max 10
int INF;
struct Matrix //快速幂模板
{
    int m[Max][Max];
    Matrix() {}
    friend Matrix operator*(Matrix &m1,Matrix &m2)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++)
            {
                temp.m[i][j]=0;
                for(k=0;k<Max;k++)
                    temp.m[i][j]+=(m1.m[i][k]*m2.m[k][j])%INF;
                temp.m[i][j]%=INF;
            }
        return temp;
    }
    friend Matrix quickpow(Matrix &M,int n)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++) //单位矩阵
                if(i==j) temp.m[i][j]=1;
                else temp.m[i][j]=0;
        while(n)
        {
            if(n&1) temp=temp*M;
            n>>=1;
            M=M*M;
        }
        return temp;
    }
};
int main()
{
    int m,k;
    while(~scanf("%d%d",&k,&m))
    {
        int i,j=9,sum=0;
        INF=m;
        Matrix res;
        mem(res.m,0);
        for(i=0;i<10;i++)
            scanf("%d",&res.m[0][i]);
        if(k<10) {pri(k%m);continue;}
        for(i=1;i<10;i++)
                res.m[i][i-1]=1;
        res=quickpow(res,k-9);
        for(i=0;i<10;i++)
            sum=(sum+res.m[0][i]*(j--))%m;
        pri(sum);
    }
    return 0;
}

HDU 1575:

先求幂后再求主对角线的和。

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 10000005
#define Max 10
#define INF 9973
#define eps 1e-7
using namespace std;
typedef long long ll;
struct Matrix //快速幂模板
{
    int m[Max][Max];
    Matrix() {}
    friend Matrix operator*(Matrix &m1,Matrix &m2)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++)
            {
                temp.m[i][j]=0;
                for(k=0;k<Max;k++)
                    temp.m[i][j]+=(m1.m[i][k]*m2.m[k][j])%INF;
                temp.m[i][j]%=INF;
            }
        return temp;
    }
    friend Matrix quickpow(Matrix &M,int n)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++) //单位矩阵
                if(i==j) temp.m[i][j]=1;
                else temp.m[i][j]=0;
        while(n)
        {
            if(n&1) temp=temp*M;
            n>>=1;
            M=M*M;
        }
        return temp;
    }
};
int main()
{
    int t;
    sca(t);
    while(t--)
    {
        int i,n,k,j=9,sum=0;
        scanf("%d%d",&n,&k);
        Matrix res;
        mem(res.m,0);
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
                sca(res.m[i][j]);
        res=quickpow(res,k);
        for(i=0;i<n;i++)
            sum=(sum+res.m[i][i])%INF;
        pri(sum);
    }
    return 0;
}

HDU 2604

分析;

解法一:同L=2时的状态递推出后面的状态:

其4个状态,分别是:fm,ff,mm,mf。

fm只可以到mm(因为fmf不符和要求了)

ff只可以到fm(同理)

mm可以到mm,mf

mf可以到fm,ff

所以构造的矩阵是

        fm   ff   mm  mf

fm     0     0    1      0

ff       1     0    0      0

mm   0    0     1      1

mf     1    1     0      0


解法二:同L=0到L=5值递推出来:

1 根据题目的意思,我们可以求出F[0] = 0 , F[1] = 2 , F[2] = 4 , F[3] = 6 , F[4] = 9 , F[5] = 15

2 那么根据上面前5项我们可以求出n >= 5的时候 F[n] = F[n-1]+F[n-3]+F[n-4]

    那么我们就可以构造出矩阵

    | 1 0 1 1 |     | F[n-1] |    | F[n] |

    | 1 0 0 0 |  *  | F[n-2] | = | F[n-1] |

    | 0 1 0 0 |     | F[n-3] |    | F[n-2] |

    | 0 0 1 0 |     | F[n-4] |    | F[n-3] |

设上面构造矩阵为a,则为a^(l-4)*f[4]=f[l-4].

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 10000005
#define Max 4
//#define INF 9973
#define eps 1e-7
using namespace std;
typedef long long ll;
int INF;
struct Matrix //快速幂模板
{
    int m[Max][Max];
    Matrix() {}
    friend Matrix operator*(Matrix &m1,Matrix &m2)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++)
            {
                temp.m[i][j]=0;
                for(k=0;k<Max;k++)
                    temp.m[i][j]+=(m1.m[i][k]*m2.m[k][j])%INF;
                temp.m[i][j]%=INF;
            }
        return temp;
    }
    friend Matrix quickpow(Matrix &M,int n)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++) //单位矩阵
                if(i==j) temp.m[i][j]=1;
                else temp.m[i][j]=0;
        while(n)
        {
            if(n&1) temp=temp*M;
            n>>=1;
            M=M*M;
        }
        return temp;
    }
};
int main()
{
    int i,j,k,n;
    int a[6]={0,2,4,6,9,15},b[5]={9,6,4,2};
    while(~scanf("%d%d",&k,&n))
    {
        if(k<5) {pri(a[k]%n);continue;}
        Matrix res;
        mem(res.m,0);
        int sum=0;
        INF=n;
        res.m[0][0]=res.m[0][3]=res.m[0][2]=1;
        res.m[1][0]=res.m[2][1]=res.m[3][2]=1;
        res=quickpow(res,k-4);
        for(i=0;i<Max;i++)
            sum=(sum+res.m[0][i]*b[i])%INF; //乘以前一个1到4的矩阵
        pri(sum);
    }
    return 0;
}


HDU 2256

这题确实不是自己能会的题了,而且是看了别人的解题报告看了好久才明天啥意思……唉……数学退化太快了……

分析网址:http://blog.csdn.net/chenguolinblog/article/details/10212567

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 10000005
#define Max 2
#define INF 1024
#define eps 1e-7
using namespace std;
typedef long long ll;
//int INF;
struct Matrix //快速幂模板
{
    int m[Max][Max];
    Matrix() {}
    friend Matrix operator*(Matrix &m1,Matrix &m2)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++)
            {
                temp.m[i][j]=0;
                for(k=0;k<Max;k++)
                    temp.m[i][j]+=(m1.m[i][k]*m2.m[k][j])%INF;
                temp.m[i][j]%=INF;
            }
        return temp;
    }
    friend Matrix quickpow(Matrix &M,int n)
    {
        int i,j,k;
        Matrix temp;
        for(i=0;i<Max;i++)
            for(j=0;j<Max;j++) //单位矩阵
                if(i==j) temp.m[i][j]=1;
                else temp.m[i][j]=0;
        while(n)
        {
            if(n&1) temp=temp*M;
            n>>=1;
            M=M*M;
        }
        return temp;
    }
};
int main()
{
    int t,n,sum;
    sca(t);
    while(t--)
    {
        sca(n);
        if(n==1) {pri(9);continue;}
        Matrix res;
        mem(res.m,0);
        res.m[0][0]=5,res.m[0][1]=12;
        res.m[1][0]=2,res.m[1][1]=5;
        res=quickpow(res,n-1);
        sum=(res.m[0][0]*5+res.m[0][1]*2)%INF;
        sum=(2*sum-1)%INF;
        pri(sum);
    }
    return 0;
}



你可能感兴趣的:(HDU 1757,1575,2604,2256 矩阵快速幂总结)