zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
    
  • 相关阅读:
    [Design]设计模式结构模式
    [Design] 设计模式行为模式
    [Design] Decorator Pattern
    ILIST<T>和LIST<T> 枫
    js 如何调用Windows自带的配色控件 枫
    WML语法全接触 WAP建站语言 枫
    Asp.net模板引擎技术 枫
    smarty内建函数 枫
    NameValueCollection详解 枫
    smarty循环调用问题 枫
  • 原文地址:https://www.cnblogs.com/weiyanpeng/p/11581095.html
Copyright © 2011-2022 走看看