矩阵:特殊的一维矩阵

题目链接: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;
    }
};*/
原文地址:https://www.cnblogs.com/qq936584671/p/8994200.html