【校内模拟】简单粗暴的题目(二项式展开)

探讨了给定数列和正整数k的情况下,如何高效计算特定形式的数列求和问题,利用前缀和与组合数学进行优化,实现快速求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简要题意:

给一个长为 nnn 的数列 aaa 和一个正整数 kkk,对于 i=1,2…,ni=1,2\dots,ni=1,2,n,求:

ansi=∑j=1i(∑l=jial)k ans_i=\sum_{j=1}^i(\sum_{l=j}^ia_l)^k ansi=j=1i(l=jial)k


题解:

sss 表示 aaa 的前缀和。

ansi=∑j=1i(∑l=jial)k=∑j=1i(si−sj−1)k=∑l=0ksil∑j=0i−1(−sj)k−l \begin{aligned} ans_i=&\sum_{j=1}^i(\sum_{l=j}^ia_l)^k\\ =&\sum_{j=1}^i(s_i-s_{j-1})^k\\ =&\sum_{l=0}^ks_i^l\sum_{j=0}^{i-1}(-s_j)^{k-l} \end{aligned} ansi===j=1i(l=jial)kj=1i(sisj1)kl=0ksilj=0i1(sj)kl

维护后面一个 Σ\SigmaΣ 即可。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const

using std::cerr;
using std::cout;

cs int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}

cs int N=5e4+7,K=1e2+7;

int n,k;
int C[K][K];
int a[N],b[N],s[N];

void init_C(){
	for(int re i=0;i<=k;++i){
		C[i][0]=1;
		for(int re j=1;j<=i;++j)
			C[i][j]=add(C[i-1][j],C[i-1][j-1]);
	}
}

void Main(){
	scanf("%d%d",&n,&k);
	init_C();b[0]=1,s[0]=1;
	for(int re i=1;i<=n;++i){
		scanf("%d",a+i);
		Inc(a[i],a[i-1]);int ans=0;
		for(int re j=1;j<=k;++j)
			b[j]=mul(b[j-1],a[i]);
		for(int re j=0;j<=k;++j)
			Inc(ans,mul((k-j)&1?mod-s[k-j]:s[k-j]
					,mul(b[j],C[k][j])));
		cout<<ans<<" ";
		for(int re j=0;j<=k;++j)
			Inc(s[j],b[j]);
	}
}

inline void file(){
#ifdef zxyoi
	freopen("concise.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
	freopen("concise.in","r",stdin);
	freopen("concise.out","w",stdout);
#endif
#endif
}signed main(){file();Main();return 0;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值