矩陣:特殊的一維矩陣


題目鏈接: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('\n')
#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;
    }
};*/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM