XSY #2815 净空

题意

n n n种不同的物品,每秒会随机产生一种,其中第 i i i秒的代价是 i k i^k ik。问收集到所有物品的期望代价和,答案模 998244353 998244353 998244353
1 ≤ n ≤ 100 , 0 ≤ k ≤ 100 1\leq n\leq100,0\leq k\leq100 1n100,0k100

题解

显然是minmax容斥。
a n s = ∑ i = 1 n ( − 1 ) i + 1 ( n i ) f ( i n , k ) ans=\sum_{i=1}^{n}(-1)^{i+1}{n \choose i}f(\frac{i}{n},k) ans=i=1n(1)i+1(in)f(ni,k)
这里 f ( p , k ) f(p,k) f(p,k)表示每次试验成功概率为 p p p,最早成功时间为 T T T ∑ i = 1 T i k \sum_{i=1}^{T}i^k i=1Tik的期望。
f ( p , k ) f(p,k) f(p,k)是关于通常幂的式子,不好求,容易想到通过第二类斯特林数转成下降幂来算,具体的有 f ( p , k ) = ∑ i ≥ 0 ( 1 − p ) i ( i + 1 ) k = ∑ i ≥ 0 ( 1 − p ) i ∑ j = 0 k s ( k , j ) j ! ( i + 1 j ) f(p,k)=\sum_{i\geq 0}(1-p)^i(i+1)^k=\sum_{i\geq 0}(1-p)^i\sum_{j=0}^{k}s(k,j)j!{i+1 \choose j} f(p,k)=i0(1p)i(i+1)k=i0(1p)ij=0ks(k,j)j!(ji+1)
交换求和顺序有 f ( p , k ) = ∑ j = 0 k s ( k , j ) j ! ∗ g ( 1 − p , j ) f(p,k)=\sum_{j=0}^{k}s(k,j)j!*g(1-p,j) f(p,k)=j=0ks(k,j)j!g(1p,j),其中 g ( p , k ) = ∑ i ≥ 0 p i ( i + 1 k ) g(p,k)=\sum_{i\geq 0}p^i{i+1 \choose k} g(p,k)=i0pi(ki+1)
k = 0 k=0 k=0时, g ( p , 0 ) = ∑ i ≥ 0 p i = 1 1 − p g(p,0)=\sum_{i\geq 0}p^i=\frac{1}{1-p} g(p,0)=i0pi=1p1
k = 1 k=1 k=1时, g ( p , 1 ) = ∑ i ≥ 0 p i ( i + 1 1 ) = ( ∑ i ≥ 0 p i ∗ i ) + p ∗ ( ∑ i ≥ 0 p i ( i + 1 1 ) ) g(p,1)=\sum_{i\geq 0}p^i{i+1\choose 1}=(\sum_{i\geq 0}p^i*i)+p*(\sum_{i\geq0}p^i{i+1\choose 1}) g(p,1)=i0pi(1i+1)=(i0pii)+p(i0pi(1i+1)),于是 g ( p , 1 ) = g ( p , 0 ) 1 − p = 1 ( 1 − p ) 2 g(p,1)=\frac{g(p,0)}{1-p}=\frac{1}{(1-p)^2} g(p,1)=1pg(p,0)=(1p)21
k > 1 k>1 k>1时, g ( p , k ) = ∑ i ≥ 0 p i ( i + 1 k ) = ∑ i ≥ k − 1 p i ( i + 1 k ) = p ∗ ( ∑ i ≥ k − 2 p i ∗ ( i + 1 k − 1 ) ) + p ∗ ( ∑ i ≥ k − 1 p i ( i + 1 k ) ) g(p,k)=\sum_{i\geq 0}p^i{i+1\choose k}=\sum_{i\geq k-1}p^i{i+1\choose k}=p*(\sum_{i\geq k-2}p^i*{i+1 \choose k-1})+p*(\sum_{i\geq k-1}p^i{i+1\choose k}) g(p,k)=i0pi(ki+1)=ik1pi(ki+1)=p(ik2pi(k1i+1))+p(ik1pi(ki+1)),于是 g ( p , k ) = p ∗ g ( p , k − 1 ) 1 − p = p k − 1 ( 1 − p ) k + 1 ( k > 1 ) g(p,k)=\frac{p*g(p,k-1)}{1-p}=\frac{p^{k-1}}{(1-p)^{k+1}}(k>1) g(p,k)=1ppg(p,k1)=(1p)k+1pk1(k>1)
直接按式子计算即可,时间复杂度 O ( n k ) O(nk) O(nk)

#include <bits/stdc++.h>
#define MOD 998244353

using namespace std;

typedef long long ll;

ll pow_mod(ll x,int k) {
  ll ans=1;
  while (k) {
  	if (k&1) ans=ans*x%MOD;
  	x=x*x%MOD;
  	k>>=1;
  }
  return ans;
}

ll C[105][105],strl[105][105],facd[105];

void pre(int n) {
  for(int i=0;i<=n;i++) C[i][0]=1;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
  strl[0][0]=1;
  for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++) strl[i][j]=(strl[i-1][j-1]+j*strl[i-1][j])%MOD;
  facd[0]=1;
  for(int i=1;i<=n;i++) facd[i]=facd[i-1]*i%MOD;
}

int main() {
  int n,k;
  scanf("%d%d",&n,&k);
  pre(max(n,k));
  ll ans=0;
  for(int i=1;i<=n;i++) {
  	ll p=i*pow_mod(n,MOD-2)%MOD,q=(1LL-p+MOD)%MOD;
  	p=pow_mod(p,MOD-2);
  	ll cur=p,s=0;
  	for(int j=0;j<=k;j++) {
  		s=(s+cur*strl[k][j]%MOD*facd[j])%MOD;
  		if (j) cur=cur*p%MOD*q%MOD;
  		else cur=cur*p%MOD;
	  } 
	ans=(ans+s*C[n][i]%MOD*((i&1)?1:MOD-1))%MOD;
  }
  printf("%lld\n",ans);
  return 0;
}
附记

这是一个水题。
为什么要为这个题写博呢?因为我闹了笑话。
今天模拟赛出了这题,然后我花了5min秒了,然后dcx也秒了。后来他找我说他觉得数据错了,我跟他对了一下100 100的输出,是一样的,于是找到zjt要求改数据。然而场上并没有其他人写了正解或是自以为正解的东西,于是就照我们的做法造了数据。
晚上被zjt找到我们,要我们测测1 1的数据,结果发现输出了0。
这是怎么回事呢?冷静推演了很久,发现我在推式子的时候把 ( i + 1 ) k (i+1)^k (i+1)k当做了 i k i^k ik来算,大体上是一样的(可以自己推推)。唯一区别是在 k = 1 k=1 k=1时,并不需要特判,也就是 g ( p , k ) = p k ( 1 − p ) k + 1 ( k &gt; 0 ) g(p,k)=\frac{p^k}{(1-p)^{k+1}}(k&gt;0) g(p,k)=(1p)k+1pk(k>0)
为什么输出会撞上呢?问了问dcx,虽然我们推的式子不同,可是都把 ( i + 1 ) k (i+1)^k (i+1)k当成了 i k i^k ik
最后发现原来的数据是对的,感觉极度尴尬。
自闭了。

扩展

稍微推导一下,发现运用等幂和其实可以做到 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)的复杂度。代码还没有。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值