51Nod 1161 - Partial Sums(组合数找规律)
题目链接 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1161
【题目描述】
给出一个数组A,经过一次处理,生成一个数组S,数组S中的每个值相当于数组A的累加,比如:A = {1 3 5 6} => S = {1 4 9 15}。如果对生成的数组S再进行一次累加操作,{1 4 9 15} => {1 5 14 29},现在给出数组A,问进行K次操作后的结果。(每次累加后的结果 mod 10^9 + 7)
Input
第1行,2个数N和K,中间用空格分隔,N表示数组的长度,K表示处理的次数(2 <= n <= 5000, 0 <= k <= 10^9, 0 <= a[i] <= 10^9)
Output
共N行,每行一个数,对应经过K次处理后的结果。每次累加后mod 10^9 + 7。
Input示例
4 2
1
3
5
6
Output示例
1
5
14
29
【思路】
找规律…,写出前面几项可以发现最终第 项的值是原来前 项 的一个多项式,且系数是一个斜着的组合数,最终第 项的答案是 组合数可以用下面的式子递推,
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5005;
const int mod=1e9+7;
int n,k;
int a[maxn];
ll inv[maxn];
ll ans[maxn];
void getInv(ll p){
inv[1]=1;
for(int i=2;i<maxn;i++){
inv[i]=(p-(p/i))*inv[p%i]%p;
}
}
int main(){
getInv(mod);
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=n;++i){
ll C=1;
for(int j=0;j<=i-1;++j){
ans[i]=(ans[i]+C*a[i-j]%mod)%mod;
if(j<i-1) C=C*(k+j)%mod*inv[j+1]%mod;
}
}
for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
return 0;
}