题目链接: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; } };*/