題目鏈接: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; } };*/