数字
链接:https://www.nowcoder.com/acm/contest/109/C
来源:牛客网
给定长度为n的数组a,定义一次操作为:
1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007;
2. 执行a = s;
现在问k次操作以后a长什么样。
1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007;
2. 执行a = s;
现在问k次操作以后a长什么样。
输入描述:
第一行两个整数n,k(1 <= n <= 2000, 0 <= k <= 1,000,000,000);
第二行n个整数表示a数组(0 <= a
i
<= 1,000,000,000)。
输出描述:
一行n个整数表示答案。
先列出前几项找规律
k=1: 1 1,1 1,1,1
k=2: 1 1+1,1 1+1+1,1+1,1
k=3: 1 (1+1)+1,1 (1+1+1)+(1+1)+1,(1+1)+1,1
k=4: 1 (1+1+1)+1,1 (1+1+1+1+1+1)+(1+1+1)+1,(1+1+1+1)+1
用公式表示
k=1: 1 1,1 1,1,1 .... 1,1,1,1,1,1,1,1
k=2: 1 2,1 3,2,1 .... n,n-1,n-2....1
k=3: 1 2*(2+1)/2,1 3*(3+1)/2,2*(2+1)/2,1 .... n*(n+1)/2,(n-1)*(n-1+1)/2,...1
k=4: 1 2*(2+1)*(2+2)/(2*3),1 3*(3+1)*(3+2)/(2*3),2*(2+1)*(2+2)/(2*3),1 .... n*(n+1)*(n+2)/(2*3),(n-1)*n*(n+1)/(2*3),1
所以最终结论是,在进行K次变换后,乘数是有一定关系的。也就是后一项(n)是前一项的 (n+k-1)/(n-1)倍(从分子可以看出来)
可以知道最终第一项乘数一定是1,第二项是k,那么就写一下就可以了.
公式表示那里利用的是数学归纳法:1+2+3+..n=n*(n+1)/2
1*(1+1)/2+2*(2+1)/2+..n*(n+1)/2= n*(n+1)*(n+2)/6
1*(1+1)*(1+2)/6+2*(2+1)*(2+2)/6+..n*(n+1)*(n+2)/6=n*(n+1)*(n+2)*(n+3)/24
............
#include<map> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e3+88; const int P=1e9+7; int inv[N],n,a[N],k,C[N],b[N]; void init(){ inv[1]=1; for(int i=2;i<=2000;++i) inv[i]=1LL*inv[P%i]*(P-P/i)%P; } int main(){ scanf("%d%d",&n,&k); init(); C[0]=1; for(int i=1;i<=n;++i) C[i]=1LL*C[i-1]*(k+i-1)%P*inv[i]%P; for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=n;++i) { int now=0; for(int j=1;j<=i;++j) now=(1LL*C[i-j]*a[j]%P+now)%P; b[i]=now; } for(int i=1;i<=n;++i) printf("%d%c",b[i],i==n?'\n':' '); }