• LOJ6402


    链接

    原题条件相当于是(a)是一个排列,每种排列出现概率随机。

    考虑从(1 o n)插入排列中,容易观察到只要后面还有空位,那么前缀一定是相连的。

    由这个过程可以观察到一些性质:

    • 连通块是一段区间
    • 相邻连通块的最大最小值区间不交(即:合并只有一种方案)

    (F(x))是长度为(i)的排列组成一个联通块的(OGF)([x^0]F = 0)),(T(x) = sum _i i!x^i)

    容易得到:

    [egin{aligned} frac 1 {(1-F)} &= T \ F &= 1- frac 1T end{aligned} ]

    (G = sum [x^i]F imes ix^i)

    则:

    [ANS = frac 1 {1-G} ]

    复杂度(O(nlog n))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e6+5;
    typedef long long ll;
    const int mod=998244353,g=3;
    int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
    int sub(int a,int b){a-=b;return a<0?a+mod:a;}
    int mul(int a,int b){return (ll)a*b%mod;}
    int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
    /* math */
    
    namespace Template_poly{
    	typedef vector<int> poly;
    	int rev[N];
    	poly poly_add(poly A,poly B){
    		A.resize(max(A.size(),B.size()));
    		for(size_t i=0;i<B.size();i++)A[i]=add(A[i],B[i]);
    		return A;
    	}
    	poly poly_sub(poly A,poly B){
    		A.resize(max(A.size(),B.size()));
    		for(size_t i=0;i<B.size();i++)A[i]=sub(A[i],B[i]);
    		return A;
    	}
    	void DFT(int *t,int n,int type){
    		int l=0;while(1<<l<n)++l;
    		for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    		for(int i=0;i<n;i++)if(rev[i]>i)swap(t[rev[i]],t[i]);
    		for(int step=1;step<n;step<<=1){
    			int wn=qpow(g,(mod-1)/(step<<1));
    			for(int i=0;i<n;i+=step<<1){
    				int w=1;
    				for(int k=0;k<step;k++,w=mul(w,wn)){
    					int x=t[i+k],y=mul(t[i+k+step],w);
    					t[i+k]=add(x,y),t[i+k+step]=sub(x,y);
    				}
    			}
    		}
    		if(type==1)return;
    		for(int i=1;i<n-i;i++)swap(t[i],t[n-i]);
    		int inv=qpow(n,mod-2);
    		for(int i=0;i<n;i++)t[i]=mul(t[i],inv);
    	}
    	poly NTT(poly A,int n,poly B,int m){
    		static poly res,PolA,PolB;
    		PolA=A,PolB=B;
    		int len=1;while(len < n+m)len<<=1;
    		res.resize(len);
    		PolA.resize(len),PolB.resize(len);
    		DFT(&PolA[0],len,1);DFT(&PolB[0],len,1);
    		for(int i=0;i<len;i++) res[i]= mul(PolA[i],PolB[i]);
    		DFT(&res[0],len,-1);
    		res.resize(n+m-1);
    		return res;
    	}
    	poly NTT(poly A,poly B){
    		return NTT(A,A.size(),B,B.size());
    	}
    	poly poly_inv(poly A,int n){
    		if(n==1)return poly(1,qpow(A[0],mod-2));
    		int len=1<<((int)ceil(log2(n))+1);
    		poly x=poly_inv(A,(n+1)>>1),y;
    		x.resize(len),y.resize(len);
    		for(int i=0;i<n;i++)y[i]=A[i];
    		DFT(&x[0],len,1),DFT(&y[0],len,1);
    		for(int i=0;i<len;i++)x[i]=mul(x[i],sub(2,mul(x[i],y[i])));
    		DFT(&x[0],len,-1);
    		x.resize(n);
    		return x;
    	}
    	poly poly_inv(poly A){
    		return poly_inv(A,A.size());
    	}
    }
    using namespace Template_poly;
    int n;
    poly f,fc;
    
    int main()
    {
    	cin >> n;
    	fc.resize(n+1);
    	fc[0] = 1;for(int i=1;i<=n;i++)fc[i] = mul(fc[i-1],i);
    	f = poly_inv(fc);
    	f[0] = sub(f[0],1);
    	for(int i=0;i<=n;i++)f[i] = mod - mul(i, mod - f[i]);
    	f[0] = add(f[0],1);
    	f = poly_inv(f);
    	cout << f[n] << endl;
    }
    
    
    
  • 相关阅读:
    【工业控制】What is a Waveform
    【工业控制】什么是波形
    【工业控制】学习喷墨打印技术 怎么能不知道波形
    【工业控制】UV打印机喷头波形和墨水关系
    VMware-workstation-full序列码
    【Centos】Centos7.5取消自动锁屏功能
    微信公众平台开发入门教程(图文)
    微信公众平台开发(34)微相册
    微信公众平台开发(33)在线点歌/在线音乐
    微信公众平台开发(32)快递物流
  • 原文地址:https://www.cnblogs.com/weiyanpeng/p/11581095.html
Copyright © 2020-2023  润新知