C. Partial Sums
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You've got an array a, consisting of n integers. The array elements are indexed from 1 to n. Let's determine a two step operation like that:
- First we build by the array a an array s of partial sums, consisting of n elements. Element number i (1 ≤ i ≤ n) of array s equals . The operation x mod y means that we take the remainder of the division of number x by number y.
- Then we write the contents of the array s to the array a. Element number i (1 ≤ i ≤ n) of the array s becomes the i-th element of the array a (ai = si).
You task is to find array a after exactly k described operations are applied.
Input
The first line contains two space-separated integers n and k (1 ≤ n ≤ 2000, 0 ≤ k ≤ 109). The next line contains n space-separated integers a1, a2, ..., an — elements of the array a (0 ≤ ai ≤ 109).
Output
Print n integers — elements of the array a after the operations are applied to it. Print the elements in the order of increasing of their indexes in the array a. Separate the printed numbers by spaces.
Examples
input
Copy
3 1 1 2 3
output
Copy
1 3 6
input
Copy
5 0 3 14 15 92 6
output
Copy
3 14 15 92 6
题目大意:
有一个长度为N的数组,每次用它的前缀和数组代替它,求执行K次操作后的数组。
思路:
通过计算前几项,找到规律,上三角矩阵进行k次幂后的第一行就是系数,
解决方法,通过特殊三角矩阵的快速幂求解 或者通过组合数学 C(i + k,i)的规律,计算然后求解
矩阵快速幂解决方法:2402ms
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define pppp cout<<endl;
#define EPS 1e-8
#define LL long long
#define ULL unsigned long long //1844674407370955161
#define INT_INF 0x3f3f3f3f //1061109567
#define LL_INF 0x3f3f3f3f3f3f3f3f //4557430888798830399
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
int read()//输入外挂
{
int ret=0, flag=0;
char ch;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
ret = ch - '0';
while((ch=getchar())>='0'&&ch<='9')
ret=ret*10+(ch-'0');
return flag ? -ret : ret;
}
const LL MOD = 1000000007;
const int maxn=2000+3;
int N,K;
LL a[maxn],h[maxn],temp[maxn];
LL b[maxn];//最终存储的结果
void mul(LL *A,LL *B)//矩阵A乘矩阵B,结果储存在A中
{
memset(temp,0,sizeof(temp));
for(int i=1; i<=N; ++i)
for(int j=1; j<=i; ++j)
temp[i]=(temp[i]+A[j]*B[i-j+1])%MOD;
for(int i=1; i<=N; ++i)
A[i]=temp[i];
}
void pow(LL n)//矩阵快速幂,结果储存在b中
{
for(int i=1; i<=N; ++i) //初始状态矩阵最上层全为1
h[i]=1;
memset(b,0,sizeof(b));
b[1]=1;//单位矩阵第一行,因为只求的第一行,改第一个就行
while(n>0)
{
if(n&1)
mul(b,h);
mul(h,h);
n>>=1;
}
}
LL num[maxn];
int main()
{
while(~scanf("%d%d",&N,&K))
{
for(int i=1;i<=N;++i)
scanf("%lld",&num[i]);
pow(K);
for(int i=1;i<=N;++i)
{
LL tem=0;
for(int j=1;j<=i;++j)
tem=(tem+num[j]*b[i-j+1]%MOD)%MOD;
printf("%lld ",tem);
}
printf("\n");
}
return 0;
}
组合数解决方式:186ms
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define pppp cout<<endl;
#define EPS 1e-8
#define LL long long
#define ULL unsigned long long //1844674407370955161
#define INT_INF 0x3f3f3f3f //1061109567
#define LL_INF 0x3f3f3f3f3f3f3f3f //4557430888798830399
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
const int dr[]= {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]= {-1, 1, 0, 0, -1, 1, -1, 1};
inline int read()//输入外挂
{
int ret=0, flag=0;
char ch;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
ret = ch - '0';
while((ch=getchar())>='0'&&ch<='9')
ret=ret*10+(ch-'0');
return flag ? -ret : ret;
}
const LL MOD=1000000007;
LL inv[2050];
void init()
{
inv[1]=1;
for(int i=2;i<=2050;++i)
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
}
LL C(LL n,LL m)
{
LL res=1;
for(int i=1;i<=m;++i)
res=res*inv[i]%MOD*(n-i+1)%MOD;
return res;
}
LL num[2050];
LL c[2050];
int main()
{
init();
LL n,k;
while(~scanf("%lld%lld",&n,&k))
{
for(int i=1;i<=n;++i)
scanf("%lld",&num[i]);
for(int i=0;i<=n;++i)
c[i]=C(k+i-1,i);
for(int i=1;i<=n;++i)
{
LL tem=0;
for(int j=1;j<=i;++j)
tem=(tem+num[j]*c[i-j]%MOD)%MOD;
printf("%lld ",tem);
}
printf("\n");
}
return 0;
}