我们把\(S(i, j)j!\)看成是把\(i\)个球每次选择一些球(不能为空)扔掉,选\(j\)次后把所有球都扔掉的情况数(顺序有关)。因此\(S(i, j)j! = i![x^i](e^x - 1)^j\)

为了求出答案,我们需要研究如下的生成函数的性质。

\(P(x) = \sum_{i = 0}^{n}(2e^x - 2)^i = \sum_{i = 0}^{n} 2^i \sum_{j = 0}^{i} (-1)^{i - j}e^{jx} {i \choose j} = \sum_{j = 0}^{n} e^{jx}\sum_{i = j}^{n} 2^i(-1)^{i - j} {i \choose j}\)

令\(a_j = \sum_{i = j}^{n} (-2)^i {i \choose j}\)。在线性时间内计算\(a_j\)是个经典的问题。

则\(a_0\)是很容易计算的。

且\(j \ge 1\)时:

\(a_j\)

\(= \sum_{i = j}^{n} (-2)^i ({i - 1 \choose j} + {i - 1 \choose j - 1})\)

\(= -2\sum_{i = j}^{n - 1} (-2)^i{i \choose j} -2\sum_{i = j - 1}^{n - 1} (-2)^i{i \choose j - 1}\)

\(= -2a_j + 2(-2)^{n} {n \choose j} - 2a_{j - 1} + 2(-2)^{n} {n \choose j - 1}\)

转换为递推式\(a_j = \frac{1}{3} (2(-2)^n {n \choose j} + 2(-2)^n{n \choose j - 1} - 2a_{j - 1})\)

欲求的答案就是\(\sum_{j = 0}^{n} (-1)^ja_j \sum_{i = 0}^{n} i![x^i]e^{jx}\)

我们发现答案就是\(\sum_{i = 0}^{n} i![x^i]e^{jx} = \sum_{i = 0}^{n} j^i\),可以使用等比数列求和公式计算。

我们需要计算\(j^{n + 1}\),这可以先计算出\(j\)为素数处的取值,然后再用线性筛算出\(1 \leq j \leq n\)时的取值。复杂度变成了\(O(\frac{n}{\ln n} \cdot log_2{n}) = O(n)\)

于是,我们在\(O(n)\)的时间内做出了本题。顺便获得目前的rk1.

代码如下:

#include <bits/stdc++.h>
#define debug(x) cerr << #x << " " << (x) << endl
using namespace std; const int N = 100005;
const long long mod = 998244353ll; int n, pri[N], cnt = 0;
bool is_pri[N];
long long pw1[N], pw2[N], inv[N], binom[N], a[N], ans = 0ll; long long qpow (long long a, long long b) {
long long res = 1ll;
for (; b; b >>= 1, a = a * a % mod) {
if (b & 1) res = res * a % mod;
}
return res;
} void init () {
pw1[1] = pw2[0] = inv[1] = 1ll;
for (int i = 1; i <= max(n, 3); i++) is_pri[i] = (i != 1), pw2[i] = 2ll * (mod - pw2[i - 1]) % mod;
for (int i = 2; i <= max(n, 3); i++) {
inv[i] = (mod / i) * (mod - inv[mod % i]) % mod;
if (is_pri[i]) pw1[i] = qpow(i, n + 1), pri[cnt++] = i;
for (int j = 0; j < cnt && i * pri[j] <= n; j++) {
is_pri[i * pri[j]] = false;
pw1[i * pri[j]] = pw1[i] * pw1[pri[j]] % mod;
if (i % pri[j] == 0) break;
}
}
binom[0] = 1ll;
for (int i = 1; i <= n; i++) binom[i] = binom[i - 1] * (n - i + 1) % mod * inv[i] % mod;
} int main () {
scanf("%d", &n), init(); a[0] = 0ll;
for (int i = 0; i <= n; i++) a[0] = (a[0] + pw2[i]) % mod;
for (int i = 1; i <= n; i++) {
a[i] = pw2[n] * (binom[i] + binom[i - 1]) % mod;
a[i] = (a[i] - a[i - 1] + mod) % mod;
a[i] = 2ll * a[i] % mod * inv[3] % mod;
} for (int i = 0; i <= n; i++) {
if (!i) ans = (ans + a[i]) % mod;
else if (i == 1) ans = (ans + mod * mod - a[i] * (n + 1)) % mod;
else if (i & 1) ans = (ans + mod * mod - a[i] * (pw1[i] + mod - 1) % mod * inv[i - 1]) % mod;
else ans = (ans + a[i] * (pw1[i] + mod - 1) % mod * inv[i - 1]) % mod;
}
printf("%lld\n", ans);
return 0;
}

「TJOI / HEOI2016」求和 的一个优秀线性做法的更多相关文章

  1. loj2058 「TJOI / HEOI2016」求和 NTT

    loj2058 「TJOI / HEOI2016」求和 NTT 链接 loj 思路 \[S(i,j)=\frac{1}{j!}\sum\limits_{k=0}^{j}(-1)^{k}C_{j}^{k ...

  2. LOJ #2058「TJOI / HEOI2016」求和

    不错的推柿子题 LOJ #2058 题意:求$\sum\limits_{i=0}^n\sum\limits_{j=0}^nS(i,j)·2^j·j!$其中$ S(n,m)$是第二类斯特林数 $ Sol ...

  3. loj2058 「TJOI / HEOI2016」求和

    推柿子 第二类斯特林数的容斥表达 fft卡精度就用ntt吧qwq. #include <iostream> #include <cstdio> using namespace ...

  4. 「TJOI / HEOI2016」字符串

    「TJOI / HEOI2016」字符串 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为 \(n\) 的字符串 \(s\),和 ...

  5. loj #2055. 「TJOI / HEOI2016」排序

    #2055. 「TJOI / HEOI2016」排序   题目描述 在 2016 年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个 ...

  6. loj#2054. 「TJOI / HEOI2016」树

    题目链接 loj#2054. 「TJOI / HEOI2016」树 题解 每次标记覆盖整棵字数,子树维护对于标记深度取max dfs序+线段树维护一下 代码 #include<cstdio> ...

  7. AC日记——#2054. 「TJOI / HEOI2016」树

    #2054. 「TJOI / HEOI2016」树 思路: 线段树: 代码: #include <cstdio> #include <cstring> #include < ...

  8. AC日记——#2057. 「TJOI / HEOI2016」游戏 LOJ

    #2057. 「TJOI / HEOI2016」游戏 思路: 最大流: 代码: #include <cstdio> #include <cstring> #include &l ...

  9. loj#2059. 「TJOI / HEOI2016」字符串 sam+线段树合并+倍增

    题意:给你一个子串,m次询问,每次给你abcd,问你子串sa-b的所有子串和子串sc-d的最长公共前缀是多长 题解:首先要求两个子串的最长公共前缀就是把反过来插入变成最长公共后缀,两个节点在paren ...

随机推荐

  1. ixgbe 驱动 为xxx驱动做准备1

    网卡都是pci设备,因此这里每个网卡驱动其实就是一个pci驱动.并且intel这里是把好几个万兆网卡(82599/82598/x540)的驱动做在一起的.V4L2 一样几个类型摄像头合并在一起 先说一 ...

  2. 重构克隆rbd的数据

    前言 之前写过一篇重构rbd的元数据的文章,讲的是如果rbd的元数据丢失了,数据还在的时候怎么恢复相关的元数据,但是实际使用的场景是,集群可能崩溃了,数据还在,osd无法拉起来,数据又很重要,需要把数 ...

  3. rgw的rgw_thread_pool_size配置调整

    前言 在比对rgw的不同前端的区别的时候,官方说civetweb是通过线程池来控制连接的,beast是后面加入了流控相关的,这块一直也没有调整过相关的参数,然后通过ab压测了一下,还是有很明显的区别的 ...

  4. Spring第三天,详解Bean的生命周期,学会后让面试官无话可说!

    点击下方链接回顾往期 不要再说不会Spring了!Spring第一天,学会进大厂! Spring第二天,你必须知道容器注册组件的几种方式!学废它吊打面试官! 今天讲解Spring中Bean的生命周期. ...

  5. linux centos 6.x 装机后基本优化

    1.关闭SELinux /etc/selinux/config配置文件内替换 se -i 's/SELINUX=enforcing/SELINUX=disabled/g'需要重启grep SELINU ...

  6. Java中的Socket用法

    转发链接:https://www.cnblogs.com/zhanglei93/p/6217384.html (1)Java中的Socket用法 Java中的Socket分为普通的Socket和Nio ...

  7. ubuntu16.04搭建vulhub环境

    简介 Vulhub官方中文教程https://github.com/vulhub/vulhub/blob/master/README.zh-cn.md 环境:ubuntu16.04.5 python3 ...

  8. MathType可以和哪些Microsoft Office版本一起使用?

    Office类软件可能是我们碰到电脑后,最先接触到的电脑软件了.尤记得,当初的微机课一开始就会讲word和excel的使用,一开始可能学不太明白,但后来越来越频繁的使用office软件,不说offic ...

  9. 【基于PUPPETEER前端自动化框架】【一】TypeScript+Puppeteer+Jest 整合

    前提:掌握Jest + Puppeteer 1.Jest环境配置 2.Jest-MATCHERS匹配器 3.Jest-全局变量设置 4.Puppeteer安装 5.Puppeteer元素获取 6.Pu ...

  10. 关于redis在cluster模式化下的 分布式锁的探索

    背景 redis作为一个内存数据库,在分布式的服务的大环境下,占的比重越来越大啦,下面我们和大家一起探讨一下如何使用redis实现一个分布式锁  说明       一个分布式锁至少要满足下面几个条件 ...