zoukankan      html  css  js  c++  java
  • 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()]);
    }
    
  • 相关阅读:
    SpringBoot,来实现MySQL读写分离技术
    range范围
    tuple元组
    序列通用操作及可变序列通用操作
    list列表
    数据
    python基础知识
    charm写代码时添加快捷键
    2、添加到项目里 在⚙图标里选择Add Remote...charm初期设置(远程服务器)
    5、优化
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15107358.html
Copyright © 2011-2022 走看看