zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    【HIDS】关于HIDS的一些看法
    图片在容器内水平垂直居中显示
    C++ 实现Cholesky分解
    Minikube 安装和简单使用
    关于.net的一些记录
    C#将窗体Form嵌入主窗体Panel中的一些问题
    Pod持久化
    Maven打包包含jar包
    Adam
    [漏洞]DNS Server Spoofed Request Amplification DDoS
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7392112.html
Copyright © 2011-2022 走看看