1 条题解
-
0
自动搬运
来自洛谷,原作者为

离散小波变换°
有志不在年高,无志空长百岁搬运于
2025-08-24 22:07:27,当前版本为作者最后更新于2020-04-11 23:26:56,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题目大意
个数中选择个(可以重合),求这个数的乘积的期望。
题解
很显然,这个问题可以拆分为两部分:求方案总数,以及求所有方案的贡献和。
求方案总数
我们设表示前个数中,选择个数的方案。那么考虑第个数如何处理。
-
不选择第个数。它的方案总数为。
-
选择第个数。它的方案总数为。
那么有:
求贡献和
同样地,我们定义表示前个数中,选择个数的贡献总和。与上文类似,考虑第个数的情况。
-
不选择第个数。这一部分的贡献总和为。
-
选择第个数。这一部分的贡献总和为。
也就是说,
最后的答案为。用快速幂求出的逆元即可。
空间优化
开的空间会爆炸。因此考虑滚动数组优化。
的值只和和的值相关。因此我们只需要保留上一个枚举到的即可。具体的实现中,我们只需要用布尔变量表示当前所用的数组,而表示上一个枚举到的时所用的数组。每次枚举完,就令即可。
时间复杂度,空间复杂度。
参考代码
#include<bits/stdc++.h> #define up(l,r,i) for(int i=l;i<=r;i++) #define dn(l,r,i) for(int i=l;i>=r;i--) using namespace std; typedef long long LL; const int INF =2147483647; int qread(){ int w=1,c,ret; while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0'; while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0'; return ret*w; } const int MOD =19260817; const int MAXN =1e5+3,MAXK=300+3; int F[2][MAXK],G[2][MAXK],P[MAXN]; int n,k; bool o; int pwr(int x,int y){ int ret=1,t=x; while(y){ if(y&1) ret=(LL)ret*t%MOD; y>>=1,t=(LL)t*t%MOD; } return ret; } int main(){ n=qread(),k=qread(); up(1,n,i) P[i]=qread(); F[!o][0]=1; up(1,n,i){ F[o][0]=1; up(1,k,j)F[o][j]=(F[!o][j]+F[o][j-1])%MOD; G[o][0]=1; up(1,k,j)G[o][j]=((LL)G[!o][j]+(LL)G[o][j-1]*P[i])%MOD; o=!o; } printf("%d\n",(LL)G[!o][k]*pwr(F[!o][k],MOD-2)%MOD); return 0; } -
- 1
信息
- ID
- 4022
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者