• 51Nod-1514 美妙的序列 多项式求逆模板题


    51Nod-1514 美妙的序列 多项式求逆模板题

    题意

    某个序列满足:

    (1 -(n-1))的某个位置断开,可以使得总能从右边找到某个数且该数不大于左边的所有数就称这个序列美妙

    问长度(n)的美妙的序列方案数

    分析

    序列不美妙(iff) (exist igeq1,区间[1,i])([1,i])的排列

    那么就可以考虑枚举使得序列不美妙的“分割点”,有转移方程

    [dp[n] = n! - sum_{i=1}^{n-1}dp[i](n-i)! ]

    [G(x) = 0!x^0 + 1!x^1+ 2!x^2...\ F(x)= 0x^0 + dp[1]x^1 + dp[2]x^2... ]

    [F * G + 1= G\ F = frac{G-1}{G} ]

    代码

    #include<bits/stdc++.h>
    #define pii pair<ll,ll>
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    
    
    inline int rd(){
    	int x;
    	scanf("%d",&x);
    	return x;
    }
    
    const int MOD = 998244353;
    
    inline int mul(int a,int b){
    	int res = (ll)a * b % MOD;
    	if(res < 0) res += MOD;
    	return res;
    }
    
    inline void add(int &a,int b){
    	a += b;
    	if(a >= MOD) a -= MOD;
    }
    
    inline void sub(int &a,int b){
    	a -= b;
    	if(a < 0) a += MOD;
    }
    
    const int maxn = 1e5 + 5;
    
    int a[maxn * 3],b[maxn * 3],c[maxn * 3]; //b:1/(1+f)
    int d[maxn * 3];                        //d:f
    int ans[maxn * 3];
    
    class NTTClass{
    public:
        static const int MAXL= 21;
        static const int MAXN= 1 << MAXL;
        static const int root= 3;
        static const int MOD= 998244353;
        int rev[MAXN];
     
        inline int fast_pow(int a,int b){
            int ans=1;
            while(b){
                if(b & 1) ans = 1ll * ans * a %MOD;
                a = (ll)a * a %MOD;
                b >>= 1;
            }
            return ans;
        }
     
        inline void transform(int n,int *t,int typ){
            for(int i = 0;i < n;i++)
                if(i < rev[i]) swap(t[i],t[rev[i]]);
            for(int step = 1;step < n;step <<= 1){
                int gn = fast_pow(root,(MOD - 1)/(step << 1));
                for(int i = 0;i < n;i += (step << 1)){
                    int g = 1;
                    for(int j = 0;j < step;j++,g = (ll)g * gn %MOD){
                        int x = t[i + j],y = (ll)g * t[i + j + step] % MOD;
                        t[i + j] = (x + y)% MOD;
                        t[i + j + step]=(x - y + MOD)%MOD;
                    }
                }
            }
            if(typ == 1)return;
            for(int i = 1;i < n / 2;i++)  swap(t[i],t[n - i]);
            int inv = fast_pow(n,MOD - 2);
            for(int i = 0;i < n;i++) t[i] = (ll)t[i] * inv %MOD;
        }
     
        inline void ntt(int p,int *A,int *B,int *C){
            transform(p,A,1);
            transform(p,B,1);
            for(int i = 0;i < p;i++)C[i] =(ll)A[i] * B[i] % MOD;
            transform(p,C,-1);
        }
     
        inline void mul(int *A,int *B,int *C,int n,int m) {
            int p = 1,l = 0;
            while(p <= n + m)p <<= 1,l++;
            //printf("n = %d, m = %d
    ",n,m);
            for (int i = n + 1;i < p;i++) A[i] = 0;
            for (int i = m + 1;i < p;i++) B[i] = 0;
            //for (int i=0;i<p;i++) printf("%d ",A[i]);puts("");
            //for (int i=0;i<p;i++) printf("%d ",B[i]);puts("");
            for(int i = 0;i < p;i++) rev[i] = (rev[i >> 1]>>1) | ((i & 1) << (l - 1));
            ntt(p,A,B,C);
            //puts("C:");for (int i=0;i<p;i++) printf("%d ",C[i]);puts("");
        }
    
    	inline void getInv(int deg,int *A,int *B){
    		if(deg == 1) {
    			B[0] = fast_pow(A[0],MOD - 2);
    			return;
    		}
    		getInv((deg + 1) >> 1,A,B);
    		int p = 1,l = 0;
    		while(p < (deg << 1)) p <<= 1,l++;
    		for(int i = 0;i < p;i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (l - 1));
    		for(int i = 0;i < deg;i++) c[i] = A[i];
    		for(int i = deg;i < p;i++) c[i] = 0;
    		transform(p,c,1);
    		transform(p,B,1);
    		for(int i = 0;i < p;i++)
    			B[i] = (ll)(2 - (ll)c[i] * B[i] % MOD + MOD) % MOD * B[i] % MOD;
    		transform(p,B,-1);
    		for(int i = deg;i < p;i++) B[i] = 0;
    	}
    }NTT;
    
    
    int main(){
    	a[0] = 1;
    	for(int i = 1;i < maxn;i++)
    		a[i] = mul(a[i - 1],i);
    	for(int i = 1;i < maxn;i++)
    		d[i] = a[i];
    	d[0] = 0;
    	NTT.getInv(maxn,a,b);
    	NTT.mul(b,d,ans,maxn - 1,maxn - 1);
    	int T = rd();
    	while(T--)
    		printf("%d
    ",ans[rd()]);
    }
    
  • 相关阅读:
    hdu 1250
    hdu 4540(简单dp)
    hdu 1078+hdu1978+hdu 1428
    hdu 2208(dfs)
    hdu 3639(强连通+缩点+建反向图)+hdu 3072(最小树形图)
    hdu 1317+hdu 1535(SPFA)
    hdu 1245(最短路+bfs)
    hdu 1286( 欧拉函数 )
    Elementary Methods in Number Theory Exercise 1.4.1
    Elementary Methods in Number Theory Exercise 1.4.2
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15107358.html
Copyright © 2020-2023  润新知