4277: Sequence
Total Submit: 39 Accepted:11
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.
1 <= N <= 300, 1 <= K <= 1,000,000,000
The value of 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
Source
看似矩阵快速幂,但是这个矩阵是300*300的矩阵,很容易就爆炸了,因为矩阵乘法是n^3的,再做快速幂是logk
这个矩阵的构造应该不算是很难吧,就是填1到n,然后斜线上的值是一样的
矩阵快速幂代码
#include<stdio.h> #include<bits/stdc++.h> using namespace std; const int N=305,MD=1e9+7,INF=0x3f3f3f3f; const double eps=1e-9,e=exp(1),PI=acos(-1.); typedef long long ll; int G; struct MX { int v[N][N]; void O() { memset(v,0,sizeof v); } void E() { memset(v,0,sizeof v); for(int i=0; i<G; i++) for(int j=i;j<G;j++)v[i][j]=j-i+1; } void P() { for(int i=0; i<G; i++) for(int j=0; j<G; j++)printf(j==G-1?"%d\n":"%d ",v[i][j]); } MX operator+(const MX &b) const { MX c; c.O(); for(int i=0; i<G; i++) for(int j=0; j<G; j++)c.v[i][j]=v[i][j]+b.v[i][j]; return c; } MX operator*(const MX &b)const { MX c; c.O(); for(int k=0; k<G; k++) for(int i=0; i<G; i++) if(v[i][k])for(int j=0; j<G; j++)c.v[i][j]=(c.v[i][j]+1LL*v[i][k]*b.v[k][j]%MD)%MD; return c; } MX operator^(int p)const { MX y,x; y.E(),memcpy(x.v,v,sizeof(v)); for(; p; x=x*x,p>>=1)if(p&1)y=y*x; return y; } } a,ans; int main() { //ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int n,k; while(~scanf("%d",&n)) { G=n; a.O(); for(int i=0; i<n; i++)scanf("%d",&a.v[0][i]); scanf("%d",&k); ans.E(); ans=ans^(k-1); ans=a*ans; for(int i=0; i<n; i++)printf(i==G-1?"%d\n":"%d ",ans.v[0][i]); } return 0; }
接下来进入找规律环节,找个p的规律啊。
因为我比较傻,还以为这个还是和快速幂的拼凑有关的,就只去了打了2 4 16 256的值,很难发现规律
然后我每个都打了一次
k=0显而易见 1 2 3 4 5 6
k=1 1 2 ...
k=2 1 4 ...
反正你很快会发现就是这一项是C(i,2k-1+i)
所以你很想到组合数
但是直接求组合数可行么,是可行的,当然k很大,你不会玩
其实就是乘上新加的数,除以i,当然这个题目要除以逆元
#include<stdio.h> const int N=305,MD=1e9+7; int a[N],b[N],v[N],n,k,i,j; int main() { v[1]=b[0]=1; for(int i=2;i<N;i++)v[i]=1LL*v[MD%i]*(MD-MD/i)%MD; while(scanf("%d",&n)!=EOF) { for(i=0; i<n; i++)scanf("%d",&a[i]); scanf("%d",&k); long long t=2*k; for(i=1; i<n; i++,t++)b[i]=t*b[i-1]%MD*v[i]%MD; for(i=n-1; i>0; i--) for(j=1; j<=i; j++)a[i]=(a[i]+b[j]*1LL*a[i-j])%MD; for(i=0; i<n; i++)printf(i==n-1?"%d\n":"%d ",a[i]); } return 0; }