题解 | #武义寺#

武义寺

https://ac.nowcoder.com/acm/problem/229190

依依寺 的题解里面讲到了一个非常麻烦的公式。这里提供一个我的赛时想出来的简单做法。

对于一个排列,我们单独看待 的所有取值对答案的贡献。

回顾 的定义:

第一个满足 就是这个排列的

那么,当 刚好产生贡献时,就有两个条件要满足:

直接做显然太麻烦了,我们分开做:

1.

这点很简单。

定义 。从后往前考虑每一个数字,易得

2.

在处理完 之后,就可以自然而然地得出 的概率为

然后就可以计算答案了。

Code:

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int kMod = 998244353;

int n, fac[1000010], ivs[1000010], inv[1000010], pbs[1000010], prb[1000010], ans;

int qpow(int x, int y) {
  int rs = 1;
  for(; y; y >>= 1) {
    if(y & 1) {
      rs = rs * x % kMod;
    }
    x = x * x % kMod;
  }
  return rs;
}

int qinv(int x) {
  return qpow(x, kMod - 2);
}

void init() {
  fac[0] = 1;
  for(int i = 1; i <= 1000000; i++) {
    fac[i] = fac[i - 1] * i % kMod;
  }
  ivs[1000000] = qinv(fac[1000000]);
  for(int i = 999999; i >= 0; i--) {
    ivs[i] = ivs[i + 1] * (i + 1) % kMod;
  }
  for(int i = 1; i <= 1000000; i++) {
    inv[i] = ivs[i] * fac[i - 1] % kMod;
  }
}

signed main() {
  init();
  cin >> n;
  pbs[0] = 1;
  for(int i = 1; i <= n; i++) {
    pbs[i] = qpow(n - i + 1, i) * fac[n - i] % kMod * ivs[n] % kMod;
  }
  for(int i = 1; i <= n + 1; i++) {
    prb[i] = (pbs[i - 1] - pbs[i] + kMod) % kMod;
    ans = (ans + i * prb[i]) % kMod;
  }
  cout << ans << '\n';
  return 0;
}
全部评论

相关推荐

牛客5655:其他公司的面试(事)吗
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务