【Bzoj4555】【Luogu P4091】求和(NTT)

题面

Bzoj

Luogu

题解

先来颓柿子

$$ \sum_{i=0}^n\sum_{j=0}^iS(i,j)2^jj! \\ =\sum_{j=0}^n2^jj!\sum_{i=0}^nS(i,j) \\ \because S(n, m)=\frac1{m!}\sum_{i=0}^m(-1)^i\binom{m}{i}(m-i)^n=\sum_{i=0}^m\frac{(-1)^i}{i!}\frac{(m-i)^n}{(m-i)!} \\ \therefore=\sum_{j=0}^n2^jj!\sum_{i=0}^n\sum_{k=0}^{j}\frac{(-1)^k}{k!}\frac{(j-k)^i}{(j-k)!} \\ =\sum_{j=0}^n2^jj!\sum_{k=0}^j\frac{(-1)^k}{k!}\frac{\sum_{i=0}^n(j-k)^i}{(j-k)!} \\ =\sum_{j=0}^n2^jj!\sum_{k=0}^j\frac{(-1)^k}{k!}\frac{(j-k)^{n+1}-1}{(j-k-1)(j-k)!} $$

然后后面那一大坨可以看做卷积,因为要取模,$NTT$就好了。

#include <cstdio>
#include <algorithm>
using std::swap;

const int N = 2.7e5 + 10, Mod = 998244353, g = 3;
int n, m, P, jc[N], pow2[N], invjc[N];
int a[N], b[N], r[N], ret;

int qpow(int a, int b) {
	int ret = 1;
	while(b) {
		if(b & 1) ret = 1ll * ret * a % Mod;
		a = 1ll * a * a % Mod, b >>= 1;
	} return ret;
}

void NTT (int f[], int opt) {
	for(int i = 0; i < n; ++i) if(i < r[i]) swap(f[i], f[r[i]]);
	for(int len = 1, nl = 2; len < n; len = nl, nl <<= 1) {
		int rot = qpow(g, (Mod - 1) / nl);
		if(opt == -1) rot = qpow(rot, Mod - 2);
		for(int l = 0; l < n; l += nl) {
			int w = 1, r = l + len;
			for(int k = l; k < r; ++k, w = 1ll * w * rot % Mod) {
				int x = f[k], y = 1ll * f[k + len] * w % Mod;
				f[k] = (x + y) % Mod, f[k + len] = (x + Mod - y) % Mod;
			}
		}
	}
}

int main () {
	scanf("%d", &n), jc[0] = pow2[0] = invjc[0] = b[0] = 1, b[1] = n + 1;
	for(int i = 1; i <= n; ++i)
		jc[i] = 1ll * jc[i - 1] * i % Mod, pow2[i] = (pow2[i - 1] << 1) % Mod;
	invjc[n] = qpow(jc[n], Mod - 2);
	for(int i = n - 1; i; --i) invjc[i] = 1ll * invjc[i + 1] * (i + 1) % Mod;
	for(int i = 0; i <= n; ++i) a[i] = 1ll * invjc[i] * (i & 1 ? Mod - 1 : 1) % Mod;
	for(int i = 2; i <= n; ++i)
		b[i] = 1ll * (qpow(i, n + 1) + Mod - 1) % Mod * qpow(i - 1, Mod - 2) % Mod * invjc[i] % Mod;
	for(m = n << 1, n = 1; n <= m; n <<= 1, ++P);
	for(int i = 0; i < n; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (P - 1));
	NTT(a, 1), NTT(b, 1);
	for(int i = 0; i < n; ++i) a[i] = 1ll * a[i] * b[i] % Mod;
	NTT(a, -1); int invn = qpow(n, Mod - 2);
	for(int i = 0; i <= n; ++i)
		ret = (ret + 1ll * pow2[i] * jc[i] % Mod * a[i] % Mod * invn % Mod) % Mod;
	printf("%d\n", ret);
	return 0;
}

原文地址:https://www.cnblogs.com/water-mi/p/10198928.html

时间: 2024-10-07 21:32:44

【Bzoj4555】【Luogu P4091】求和(NTT)的相关文章

【BZOJ4555】[Tjoi2016&amp;Heoi2016]求和 NTT

[BZOJ4555][Tjoi2016&Heoi2016]求和 Description 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: S(i, j)表示第二类斯特林数,递推公式为: S(i, j) = j ∗ S(i − 1, j) + S(i − 1, j − 1), 1 <= j <= i − 1. 边界条件为:S(i, i) = 1(0 <= i), S(i, 0) = 0(1 <= i) 你能帮帮他吗? Input 输入

BZOJ4555 [Tjoi2016&amp;Heoi2016]求和 【第二类斯特林数 + NTT】

题目 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: S(i, j)表示第二类斯特林数,递推公式为: S(i, j) = j ? S(i ? 1, j) + S(i ? 1, j ? 1), 1 <= j <= i ? 1. 边界条件为:S(i, i) = 1(0 <= i), S(i, 0) = 0(1 <= i) 你能帮帮他吗? 输入格式 输入只有一个正整数 输出格式 输出f(n).由于结果会很大,输出f(n)对998244353(7

luogu P4091 [HEOI2016/TJOI2016]求和

传送门 这一类题都要考虑推式子 首先,原式为\[f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}S(i,j)*2^j*j!\] 可以看成\[f(n)=\sum_{j=0}^{n}2^j*j!\sum_{i=j}^{n}S(i,j)\] 又因为\[S(i,j)=\frac{1}{j!}\sum_{k=0}^{j}(-1)^k*\binom{j}{k}*(j-k)^i\] 所以\[f(n)=\sum_{j=0}^{n}2^j*j!\sum_{i=0}^{n}\frac{1}{j!}

【BZOJ 4555】[Tjoi2016&amp;Heoi2016]求和 NTT+第二类斯特林数

用到第二类斯特林数的性质,做法好像很多,我打的是直接ntt,由第二类斯特林数的容斥公式可以推出,我们可以对于每一个i,来一次ntt求出他与所有j组成的第二类斯特林数的值,这个时候我们是O(n^2logn)的,还不如暴力,但是我们发现,对于刚刚提到的容斥的式子,将其化为卷积形式后,其一边的每一项对于每一个i都相同,另一边的每一项是对于所有的i形成一个n项的等比数列,这样我们可以把成等比数列的一边求和,用固定的一边去卷他们的和,这时候的答案的每一项就是所有的i的这一项的和,然后我们再O(n)乘上阶乘

bzoj 4555 [Tjoi2016&amp;Heoi2016]求和 NTT 第二类斯特林数 等比数列求和优化

[Tjoi2016&Heoi2016]求和 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 679  Solved: 534[Submit][Status][Discuss] Description 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: S(i, j)表示第二类斯特林数,递推公式为: S(i, j) = j ∗ S(i − 1, j) + S(i − 1, j − 1), 1 <= j &l

Bzoj4555 [Tjoi2016&amp;Heoi2016]求和

Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 327  Solved: 262 Description 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: S(i, j)表示第二类斯特林数,递推公式为: S(i, j) = j ∗ S(i − 1, j) + S(i − 1, j − 1), 1 <= j <= i − 1. 边界条件为:S(i, i) = 1(0 <= i), S(i, 0) =

[BZOJ4555][TJOI2016&amp;HEOI2016]求和(分治FFT)

解法一:容易得到递推式,可以用CDQ分治+FFT 代码用时:1h 比较顺利,没有低级错误. 实现比较简单,11348ms #include<cstdio> #include<algorithm> #define rep(i,l,r) for (int i=l; i<=r; i++) typedef long long ll; using namespace std; const int N=(1<<18)+100,P=998244353,g=3; int n,re

luogu 4427 求和

bjoi 2018 求和 唯一一道可能切的题一个数组还没开long long就成0分了 题目大意: 一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k次方和,而且每次的k可能是不同的 此处节点深度的定义是这个节点到根的路径上的边数 思路: 考试的时候随便写了个树剖 剖下来之后搞五十个次方的前缀和 然后一个数组乘起来没开long long 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #

【BZOJ】4555: [Tjoi2016&amp;Heoi2016]求和 排列组合+多项式求逆 或 斯特林数+NTT

[题意]给定n,求Σi=0~nΣj=1~i s(i,j)*2^j*j!,n<=10^5. [算法]生成函数+排列组合+多项式求逆 [题解]参考: [BZOJ4555][Tjoi2016&Heoi2016]求和-NTT-多项式求逆 $ans=\sum_{i=0}^{n}\sum_{j=0}^{i}s(i,j)*2^j*j!$ 令$g(n)=\sum_{j=0}^{n}s(n,j)*2^j*j!$ 则ans是Σg(i),只要计算出g(i)的生成函数就可以统计答案. g(n)可以理解为将n个数划分