【BZOJ4555】[Tjoi2016&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

输入只有一个正整数

Output

输出f(n)。由于结果会很大,输出f(n)对998244353(7 × 17 × 223 + 1)取模的结果即可。1 ≤ n ≤ 100000

Sample Input

3

Sample Output

87

题解:读书少,没见过第二类斯特林数,于是去百度找了定义及通项公式。

将n个不同的球放入m个无差别的盒子中,要求盒子非空,有几种方案?

由定义可知,原题中的j<=i可以变成j<=n,所以开始推式子啦!

然后右面是什么?卷积!直接NTT完成任务。

不要忘记讨论等比数列公比为1的情况!

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll P=998244353;
const ll G=3;
const int maxn=(1<<19)+10;
int n,len;
ll ans;
ll A[maxn],B[maxn],ine[maxn],jcc[maxn],jc[maxn];
ll pm(ll x,ll y,ll z)
{
	ll ret=1;
	while(y)
	{
		if(y&1)	ret=ret*x%P;
		x=x*x%P,y>>=1;
	}
	return ret;
}
void NTT(ll *a,int f)
{
	int i,j,k,h;
	ll t;
	for(i=k=0;i<len;i++)
	{
		if(i>k)	swap(a[i],a[k]);
		for(j=len>>1;(k^=j)<j;j>>=1);
	}
	for(h=2;h<=len;h<<=1)
	{
		ll wn=pm(G,f==1?(P-1)/h:P-1-(P-1)/h,P);
		for(j=0;j<len;j+=h)
		{
			ll w=1;
			for(k=j;k<j+h/2;k++)	t=a[k+h/2]*w%P,a[k+h/2]=(a[k]-t+P)%P,a[k]=(a[k]+t)%P,w=w*wn%P;
		}
	}
	if(f==-1)
	{
		t=pm(len,P-2,P);
		for(i=0;i<len;i++)	a[i]=a[i]*t%P;
	}
}
int main()
{
	scanf("%d",&n);
	int i;
	for(len=1;len<=n+n;len<<=1);
	ine[1]=ine[0]=jcc[1]=jcc[0]=jc[1]=jc[0]=1;
	for(i=2;i<=n;i++)	ine[i]=(P-(P/i)*ine[P%i])%P,jcc[i]=jcc[i-1]*ine[i]%P,jc[i]=jc[i-1]*i%P;
	for(i=0;i<=n;i++)
	{
		A[i]=(((i&1)?-1:1)*jcc[i]+P)%P;
		if(i==1)	B[i]=(n+1)*jcc[i]%P;
		else	B[i]=(1-pm(i,n+1,P)+P)*pm(1-i,P-2,P)%P*jcc[i]%P;
	}
	NTT(A,1),NTT(B,1);
	for(i=0;i<len;i++)	A[i]=A[i]*B[i]%P;
	NTT(A,-1);
	for(i=0;i<=n;i++)	ans=(ans+jc[i]*pm(2,i,P)%P*A[i]%P)%P;
	printf("%lld",ans);
	return 0;
}
时间: 2024-08-06 11:55:20

【BZOJ4555】[Tjoi2016&Heoi2016]求和 NTT的相关文章

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]求和 【第二类斯特林数 + 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

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

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

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

【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个数划分

4555: [Tjoi2016&amp;Heoi2016]求和

我们省选的题- 考虑这个式子的组合意义,对于每一个i,枚举j表示将i个小球放入j个有序集合,且每个集合选择或者不选的方案数. 我们用f[i]表示将i个小球放入任意个有序集合,且每个集合选择或不选的方案数,则枚举最后一个集合的大小i-j,可以得到递推式: for(int i = 1;i <=n ;i ++) for(int j = 0;j < i ;j ++)f[i]=(f[i]+f[j]*c[i][j]*2); c[i][j]是组合数. 意义就是有j个小球任意组合,剩下的组成最后一个集合,且这

[Tjoi2016&amp;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 输入只有一个正整数 Output 输出f(n).由于结果会很大,输出f(n)

BZOJ 4553 Tjoi2016&amp;Heoi2016 序列

Tjoi2016&Heoi2016序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值 可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你 ,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可 .注意:每种变化最多只有一个值发生变化.在样例输入1中,所有的变化是: 1 2 3 2 2 3 1 3 3 1 1 31 2 4