zoukankan      html  css  js  c++  java
  • 矩阵:特殊的一维矩阵

    题目链接:https://www.nowcoder.com/acm/contest/109/C

    看到题目中的值很大,考虑使用矩阵快速幂。

    根据题目可以列出矩阵:

    {a[1],a[2],……,a[n]}*A={s[1],s[2],……,s[n]}

    其中s[n]=a[1]+a[2]+……+a[n]

    得出A的矩阵:

    1 1 1……1

    0 1 1……1

    0 0 1……1

    ………………

    0 0 0……1

    这是一个2000*2000大小的矩阵,但这样的矩阵只能开出一个,因为内存限制,我们最大可以开出2828*2828的矩阵,也就是我们矩阵的1.9倍。

    后来发现左下角都为0,所以可以把矩阵化简为一个三角形,通过使用map,我们可以省下近一半的空间,然而这并没有用,我们通过这样可以开出3.8个矩阵,但计算却至少需要四个矩阵的空间。

    后来又发现剩余三角形阵中的数字有一些特殊性质,即在同一条左上——右下斜线上的数字都为同一个数字,再加上打表,发现这样的矩阵只需要一维即可完成计算。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<stack>
    #include<map>
    #include<vector>
    #include<queue>
    #include<set>
    #include<iomanip>
    #include<cctype> 
    using namespace std;
    const int MAXN=1e5+5;
    const int INF=1<<30;
    const long long mod=1e9+7;
    const double eps=1e-8;
    #define ll long long
    #define edl putchar('
    ')
    #define sscc ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define ROF(i,a,b) for(int i=a;i>=b;i--)
    #define FORLL(i,a,b) for(ll i=a;i<=b;i++)
    #define ROFLL(i,a,b) for(ll i=a;i>=b;i--)
    #define mst(a) memset(a,0,sizeof(a))
    #define mstn(a,n) memset(a,n,sizeof(a))
    #define zero(x)(((x)>0?(x):-(x))<eps)
    /*
    适用矩阵:
    1 2 3 4 5
    0 1 2 3 4
    0 0 1 2 3
    0 0 0 1 2
    0 0 0 0 1 
    */ 
    const int N=2005;
    ll a[N],b[N],tmp[N],A,B,n,m;
     
    void multi(ll a[N],ll b[N],int n)
    {
        memset(tmp,0,sizeof tmp);
        for(int i=0;i<n;i++)
        for(int j=0;j<=i;j++)
            tmp[i]=(tmp[i]+a[j]*b[i-j])%mod;
        for(int i=0;i<n;i++)
        {
            a[i]=tmp[i];
        }
             
    }
    ll res[N];
    void Pow(ll a[N],ll n,ll m)
    {
        memset(res,0,sizeof res);//n是矩阵大小 
        for(int i=0;i<n;i++) res[i]=1;
        while(m)
        {
            if(m&1)
                multi(res,a,n);//res=res*a; (此处用到的multi是上面计算矩阵的函数)
            multi(a,a,n);//a=a*a
            m>>=1;
        }
    }
    int main()
    {
        ll n,k;
        cin>>n>>k;
        {
            FOR(i,0,n-1)
            a[i]=1;
            if(k==0)
            {
                FOR(i,0,n-1) cin>>b[i];
                FOR(i,0,n-1)
                {
                     
                    cout<<b[i];
                    if(i!=(n-1)) cout<<" ";
                    else cout<<endl;
                }
            }
            else
            {
                Pow(a,n,k-1);
                FOR(i,0,n-1)
                cin>>b[i];
                memset(tmp,0,sizeof tmp);
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<=i;j++)
                    tmp[i]=(tmp[i]+res[j]*b[i-j])%mod;
                    cout<<tmp[i];
                    if(i!=(n-1)) cout<<" ";
                    else cout<<endl;
                }
            }
        }
    }
    /*
    矩阵结构体写法 
    const int ssize=2005;
    struct Matrix
    {
        ll a[ssize];
        Matrix()
        {
            memset(a,0,sizeof(a));
        }
        void init()
        {
            for(int i=0;i<ssize;i++)
                    a[i]=1;
        }
        Matrix operator + (const Matrix &B)const
        {
            Matrix C;
            for(int i=0;i<ssize;i++)
                    C.a[i]=(a[i]+B.a[i])%mod;
            return C;
        }
        Matrix operator * (const Matrix &B)const
        {
            Matrix C;
            for(int i=0;i<ssize;i++)
                for(int j=0;j<ssize;j++)
                    C.a[i]=(C.a[i]+1LL*a[j]*B.a[i-j])%mod;
            return C;
        }
        Matrix operator ^ (const ll &t)const
        {
            Matrix A=(*this),res;
            res.init();
            ll p=t;
            while(p)
            {
                if(p&1)res=res*A;
                A=A*A;
                p>>=1;
            }
            return res;
        }
    };*/
  • 相关阅读:
    练习
    js简介、基本语法、类型转换、变量、运算符、分支语句、循环语句、函数、函数调用
    样式表、格式布局、流式布局
    表单
    图片热点、网页划区
    JS模拟窗口
    JavaScript 常用功能实现一览(一)
    分页打印控制 摘自于网络:http://www.cnblogs.com/joinger/articles/1807517.html
    我眼中的C#3.0 摘自于网络:http://www.cnblogs.com/joinger/articles/1297237.html
    .net ToString()用法详解与格式说明
  • 原文地址:https://www.cnblogs.com/qq936584671/p/8994200.html
Copyright © 2011-2022 走看看