1288: Sequence
Time Limit: 3 Sec Memory Limit: 128 MB 64bit IO Format: %lldSubmitted: 20 Accepted: 4
[ Submit][ Status][ Web Board]
Description
YXH is very fond of the sequence. One day he found a very interesting sequence. At time T, a sequence A is A(1) ,A(2) ,…,A(n) After one second (at time T + 1), the sequence will become A(1) ,A(2)+2A(1) ,A(3)+2A(2)+3A(1) ,…,A(n)+2A(n-1)+…+nA(1) YXH wants to know the sequence at time K. Can you solve this problem?
Input
There are multiple test cases. For each case, the first line contains a number N indicating the length of the sequence. The second line contains N numbers indicating the sequence in time 0. The third line contains a number K as description above. Technical Specification 1 <= N <= 300, 1 <= K <= 1,000,000,000 The absolute value each number in the sequence will not exceed 300.
Output
For each case, print the sequence at time K in one line. Since the answer could be very large, you should output the answer module 1,000,000,007
Sample Input
3
1 2 3
2
Sample Output
1 6 21
思路:矩阵快速幂。但是如果单纯的n*n*n*log(k)的时间复杂度会TLE。打表发现友矩阵满足a[i][j]=a[i-1][j-1](1<=i,j)。那么可以算出第一行,然后n^2推出其它的数。复杂度n*n*log(k)。
#include<bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
typedef long long ll;
struct lenka
{
int a[300][300];
};
ll f[300],d[300];
int n;
lenka cla(const lenka& a,const lenka& b)
{
lenka c;
memset(c.a,0,sizeof c.a);
for(int j=0;j<n;j++)
{
for(int k=0;k<=j;k++)c.a[0][j]=(c.a[0][j]+(ll)a.a[0][k]*(ll)b.a[k][j]%MOD)%MOD;
}
for(int i=1;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(j==0)c.a[i][j]=0;
else c.a[i][j]=c.a[i-1][j-1];
}
}
return c;
}
lenka POW(int k)
{
lenka a,res;
memset(a.a,0,sizeof a.a);
memset(res.a,0,sizeof res.a);
for(int i=0;i<n;i++)a.a[i][i]=1;
for(int i=0;i<n;i++)
{
for(int j=i;j<n;j++)res.a[i][j]=j-i+1;
}
while(k)
{
if(k&1)a=cla(res,a);
res=cla(res,res);
k>>=1;
}
return a;
}
int main()
{
int k;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)scanf("%lld",&f[i]);
scanf("%d",&k);
lenka res=POW(k);
for(int i=0;i<n;i++)
{
d[i]=0;
for(int k=0;k<n;k++)d[i]=(d[i]+res.a[k][i]*f[k])%MOD;
}
for(int i=0;i<n;i++)printf("%lld%c",d[i],i==n-1?'\n':' ');
}
return 0;
}