zoukankan      html  css  js  c++  java
  • 矩阵模板hdu5015,UVA 10655,UVA 11149

    hdu5015

    n是<=10的,可以想到点什么,,
    构造矩阵mat[n+2][n+2]
    这里写图片描述
    发现mat*a是答案矩阵第1列
    mat的m次方再乘a就是答案矩阵的第m列,取最下面的就行了

    这板不错

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int P = 10000007;
    const int N=13;
    ll n,m;
    
    struct matrix{
        ll a[N][N];
        int row,col;
        matrix():row(N),col(N){
            memset(a,0,sizeof(a));
        }
        matrix(int x,int y):row(x),col(y){
            memset(a,0,sizeof(a));
        }
        ll* operator [] (int x){
            return a[x];
        }
        matrix operator * (matrix x){
            matrix tmp ;
            for (int i=0;i<=n+1;i++)
                for (int j=0;j<=n+1;j++){
                    tmp[i][j]=0;
                    for (int k=0;k<=n+1;k++)
                        tmp[i][j]=(tmp[i][j]+a[i][k]*x[k][j])%P;
                }
            return tmp;
        }   
        void operator *= (matrix x){
            *this = *this * x;
        }
        matrix operator ^ (ll x){
            matrix ret;
            for (int i=0;i<=n+1;i++)ret[i][i]=1;
            matrix tmp = *this;
            for (;x;x>>=1,tmp*=tmp){if(x&1)ret *=tmp;}
            return ret;
        }
        void print(){
            for (int i=0;i<=n+1;i++){
                for (int j=0;j<=n+1;j++)
                    printf("%d ",a[i][j]);
                puts("");
            }
        }
    };
    
    matrix getMatrix(){
        matrix mat;
        mat[0][0]=10;
        mat[0][n+1]=1;
        for (int i=1;i<=n;i++)
            for (int j=0;j<=i;j++)mat[i][j]=1;
        for (int i=0;i<=n;i++)mat[n+1][i]=0;
        mat[n+1][n+1]=1;
        return mat;
    }
    
    int main(){
        //freopen("fuck.in","r",stdin);
        while (~scanf("%I64d%I64d",&n,&m)){
            matrix a;
            for (int i=1;i<=n;i++)scanf("%I64d",&a[i][0]);
            a[0][0] = 233,a[n+1][0] = 3;
            matrix mat = getMatrix();
            mat = (mat ^ m) * a;
            printf("%I64d
    ",mat[n][0]%P);
        }
        return 0;
    } 

    UVA 10655
    题解
    题目大意:给出a+b的值和ab的值,求a^n+b^n的值。

    题目分析:有种错误的方法是这样的:利用已知的两个方程联立,求解出a和b,进而求出答案。这种方法之所以错,是因为这种方法有局限性。联立之后会得到一个二元一次方程,只有当该方程有实数解确切的说是当某个数据满足该方程有实数解时,这种方法得到的结果才有可能正确。显然,题中数据不可能这么片面。正确的方法是这样的:

    令a+b=A,ab=B,S(n)=an+bn。
    则S(n)=an+bn=(a+b)(a^n-1+b^n-1)-a*b^n-1-a^n-1*b
    =(a+b)(an-1+bn-1)-ab(an-2+bn-2)=A*S(n-1)-B*S(n-2)  (n≥2)。
                          
    由此构造2x2的矩阵:
    matrix[1][1]=A,matrix[1][2]=-B;
    matrix[2][1]=1,matrix[2][2]=0;

    n=1或n=0时,答案显然。

    要注意:数据中可能会出现A=B=0的情况,此时a=b=0,所以不能简单的判定当A=B=0时就结束输入数据。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int N=4;
    
    struct matrix{
        ll a[N][N];
        int row,col;
        matrix():row(N),col(N){
            memset(a,0,sizeof(a));
        }
        matrix(int x,int y):row(x),col(y){
            memset(a,0,sizeof(a));
        }
        ll* operator [] (int x){
            return a[x];
        }
        matrix operator * (matrix x){
            matrix tmp ;
            for (int i=1;i<=2;i++)
                for (int j=1;j<=2;j++){
                    tmp[i][j]=0;
                    for (int k=1;k<=2;k++)
                        tmp[i][j]=(tmp[i][j]+a[i][k]*x[k][j]);
                }
            return tmp;
        }
        void operator *= (matrix x){
            *this = *this * x;
        }
        matrix operator ^ (ll x){
            matrix ret;
            for (int i=1;i<=2;i++)ret[i][i]=1;
            matrix tmp = *this;
            for (;x;x>>=1,tmp*=tmp){if(x&1)ret *=tmp;}
            return ret;
        }
        void operator ^=(ll x){
            *this = *this ^ x;
        }
        void print(){
            for (int i=1;i<=2;i++){
                for (int j=1;j<=2;j++)
                    printf("%d ",a[i][j]);
                puts("");
            }
        }
    };
    
    ll solve(ll a ,ll b ,ll n){
        if (n==0) return 2;
        if (n==1) return a;
        if (a==0&&b==0)return 0;
        matrix tra,ans;
        tra[1][1]=a;tra[1][2]=-b;
        tra[2][1]=1;tra[2][2]=0;
        ans[1][1]=a;
        ans[2][1]=2;
        ans = (tra^n)*ans;
        return ans[2][1];
    }
    
    int main(){
        //freopen("fuck.in","r",stdin);
        ll p,q,n;
        while (scanf("%lld%lld%lld",&p,&q,&n)==3){
            printf("%lld
    ",solve(p,q,n));
        }
        return 0;
    }

    UVA 11149
    题解
    题目大意:给一个n阶方阵,求A1+A2+A3+……Ak。

    题目分析:令F(k)=A1+A2+A3+……Ak。当k为偶数时,F(k)=F(k/2)(E+Ak/2),k为奇数时,F(k)=F(k/2)(E+Ak/2)+Ak。证明这两条公式也很简单,把这两条公式展开就行了。根据公式,递归即可。

    /*
     * UVA 11149    Power of Matrix
     * by cww97
    */
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int N=43;
    int n;
    
    struct matrix{
        ll a[N][N];
        int row,col;
        matrix():row(N),col(N){
            memset(a,0,sizeof(a));
        }
        matrix(int x,int y):row(x),col(y){
            memset(a,0,sizeof(a));
        }
        ll* operator [] (int x){
            return a[x];
        }
        matrix operator + (matrix x){
            matrix tmp ;
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++){
                    tmp[i][j]=(a[i][j]+x[i][j])%10;
                }
            return tmp;
        }
        void operator += (matrix x){
            *this = *this + x;
        }
        matrix operator * (matrix x){
            matrix tmp ;
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++){
                    tmp[i][j]=0;
                    for (int k=1;k<=n;k++)
                        tmp[i][j]=(tmp[i][j]+a[i][k]*x[k][j])%10;
                }
            return tmp;
        }
        void operator *= (matrix x){
            *this = *this * x;
        }
        matrix operator ^ (ll x){
            matrix ret;
            for (int i=1;i<=n;i++)ret[i][i]=1;
            matrix tmp = *this;
            for (;x;x>>=1,tmp*=tmp){if(x&1)ret *=tmp;}
            return ret;
        }
        void operator ^=(ll x){
            *this = *this ^ x;
        }
        void print(){
            for (int i=1;i<=n;i++){
                for (int j=1;j<n;j++)
                    printf("%d ",a[i][j]%10);
                printf("%d
    ",a[i][n]%10);
            }
            puts("");
        }
    }E,A;
    
    matrix f(int k){
        if (k==1)return A;
        matrix tmp = f(k>>1)*((A^(k>>1)) +E);
        if (k&1)tmp +=(A^k);
        return tmp;
    }
    
    int main(){
        //freopen("fuck.in","r",stdin);
        int k,x;
        while (scanf("%d%d",&n,&k)==2&&n){
            for (int i=1;i<=n;i++){
                for (int j=1;j<=n;j++){
                    scanf("%d",&x);
                    A[i][j]=x%10;
                }
            }
            for (int i=1;i<=n;i++)E[i][i]=1;
            A = f(k);
            A.print();
        }
        return 0;
    }
    
  • 相关阅读:
    在博客园安了新家,开心哦!
    ViewState与Session的区别(转)
    什么是web.config .net配置文件介绍
    YUI Grid CSS的优雅设计(转)
    css reset
    Windows、(*)nux回忆录 作为架构师的你 值得拥有 O(∩_∩)O~
    .NET互联网网站架构(非原创)
    重构与设计解析(非原创)
    SQL Server2005索引简介
    mongodb相关
  • 原文地址:https://www.cnblogs.com/cww97/p/7533986.html
Copyright © 2011-2022 走看看