zoukankan      html  css  js  c++  java
  • CF1516E Baby Ehab Plays with Permutations

    CF1516E Baby Ehab Plays with Permutations

    发现交换 (k) 次意味着至少 (n-k) 个循环。

    交换次数还要和 n-循环数 (mod 2) 同余,因为每交换一次要么循环数少一个,要么多一个。

    可以发现满足以上两个条件的排列一定可以得到。

    于是通过第一类斯特林数来统计,答案就是

    [ans_k=sum_{i=n-k}^{n}[imod 2 = kmod 2]S_1(n,i) ]

    (S_1) 就是第一类斯特林数。

    也就是说要求第一类斯特林数的后 (k) 项。

    众所周知

    [x^{overline{n}}=prod_{i=0}^{n-1}(x+i)=sum_{i=0}^{n}egin{bmatrix}n\iend{bmatrix}x^i ]

    如果把常数 (i) 乘到 (x) 上,我们就只需要提取前 (k) 项,方便许多,也就是我们转而计算

    [prod_{i=0}^{n}(1+ix) ]

    (k) 项。

    [f(x)=prod_{i=0}^{n-1}(1+ix) ]

    套路取 (ln)(exp)

    [ln f(x)=sum_{i=0}^{n-1}ln (1+ix) ]

    [=sum_{i=0}^{n-1}-sum_{j=1}^{k}dfrac{(-i)^jx^j}{j} ]

    [=sum_{j=1}^{k}dfrac{(-1)^{j+1}x^j}{j}sum_{i=0}^{n-1}i^j ]

    后面是自然数幂和前缀和。

    可以构造 EGF 来计算:

    [sum_{j=0}^{n-1}sum_{i=0}^{n-1}i^jdfrac{x^j}{j!} =sum_{j=0}^{n-1}e^{ix}=dfrac{1-e^{nx}}{1-e^x} ]

    注意分母常数项为 (0),要上下同时除以 (x) 再计算。

    如果换成 MTT 可以 (O(klog k)),但是这么小数据范围不是很划算。于是我去补了套 (O(n^2)) 的全家桶qwq

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mkp make_pair
    #define pb push_back
    #define sz(v) (int)(v).size()
    typedef long long LL;
    typedef double db;
    template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
    template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
    #define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
    #define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    const int N = 205;
    
    namespace poly {
    #define mod 1000000007
    inline int qpow(int n, int k) {
    	int res = 1;
    	for(; k; k >>= 1, n = 1ll * n * n % mod)
    		if(k & 1) res = 1ll * n * res % mod;
    	return res; 
    }
    int inv[N], fac[N], ifc[N];
    inline void init(const int &n = N - 1) {
    	inv[1] = 1;
    	for(int i = 2; i <= n; ++i) inv[i] = 1ll * inv[mod % i] * (mod - mod / i) % mod;
    	fac[0] = 1;
    	for(int i = 1; i <= n; ++i) fac[i] = 1ll * i * fac[i - 1] % mod;
    	ifc[n] = qpow(fac[n], mod - 2);
    	for(int i = n - 1; i >= 0; --i) ifc[i] = 1ll * ifc[i + 1] * (i + 1) % mod;
    }
    vector <int> operator * (const vector <int> &a, const vector <int> &b) {
    	int n = a.size(), m = b.size();
    	vector <int> res(n + m - 1, 0);
    	for(int i = 0 ; i < n; ++i)
    		for(int j = 0; j < m; ++j)
    			res[i + j] = (res[i + j] + 1ll * a[i] * b[j]) % mod;
    	return res;
    }
    vector <int> poly_inv(const vector <int> &a) {
    	int n = a.size();
    	vector <int> res(n);
    	res[0] = qpow(a[0], mod - 2);
    	for(int i = 1; i < n; ++i) {
    		int tmp = 0;
    		for(int j = 0; j < i; ++j)
    			tmp = (tmp + 1ll * res[j] * a[i - j]) % mod;
    		res[i] = 1ll * qpow(a[0], mod - 2) * (mod - tmp) % mod;
    	}
    	return res;
    }
    vector <int> deriv(const vector <int> &a) {
    	int n = a.size();
    	vector <int> res;
    	if(n == 1) return res;
    	res.resize(n - 1);
    	for(int i = 0; i < n - 1; ++i) 
    		res[i] = 1ll * a[i + 1] * (i + 1) % mod;
    	return res;
    }
    
    vector <int> integ(const vector <int> &a) {
    	int n = a.size();
    	vector <int> res(n + 1);
    	res[0] = 0;
    	for(int i = 1; i < n; ++i)
    		res[i] = 1ll * a[i - 1] * inv[i] % mod;
    	return res;
    }
    vector <int> poly_ln(const vector <int> &a) {
    	int n = a.size();
    	vector <int> res = integ(deriv(a) * poly_inv(a));
    	res.resize(n);
    	return res;
    }
    vector <int> poly_exp(const vector <int> &a) {
    	int n = a.size();
    	vector <int> res(n);
    	res[0] = 1;
    	for(int i = 1; i < n; ++i) {
    		int tmp = 0;
    		for(int j = 0; j < i; ++j)
    			tmp = (tmp + 1ll * a[j + 1] * (j + 1) % mod * res[i - 1 - j]) % mod;
    		res[i] = 1ll * tmp * inv[i] % mod;
    	}
    	return res;
    }
    
    }
    using namespace poly;
    
    int n, k;
    signed main() {
    	cin >> n >> k, ++k, init();
    	vector <int> a(k), b(k), ans(k);
    	for(int i = 0, j = n; i < k; ++i, j = 1ll * j * n % mod)
    		a[i] = 1ll * j * ifc[i + 1] % mod, b[i] = ifc[i + 1];
    	a = a * poly_inv(b), a.resize(k);
    	for(int i = 0; i < k; ++i) a[i] = 1ll * fac[i] * a[i] % mod;
    	b[0] = 0;
    	for(int i = 1; i < k; ++i) {
    		int tmp = 1ll * a[i] * inv[i] % mod;
    		b[i] = i & 1 ? tmp : mod - tmp;
    	}
    	b = poly_exp(b);
    	for(int i = 0; i < k; ++i) {
    		ans[i] = b[i];
    		if(i - 2 >= 0) ans[i] = (ans[i] + ans[i - 2]) % mod;
    	}
    	for(int i = 1; i < k; ++i) printf("%d ", ans[i]);
    	return 0; 
    }
    
    路漫漫其修远兮,吾将上下而求索
  • 相关阅读:
    vue2.0 + vux (六)NewsList 资讯页 及 NewsDetail 资讯详情页
    vue2.0 + vux (五)api接口封装 及 首页 轮播图制作
    vue2.0 + vux (四)Home页
    vue2.0 + vux (三)MySettings 页
    vue2.0 + vux (二)Footer组件
    vue2.0 + vux (一)Header 组件
    vue2 + typescript2 自定义过滤器
    flexible.js + makegrid.js 自适应布局
    vue-router钩子beforeRouteEnter函数获取到this实例
    weex 项目搭建
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14688359.html
Copyright © 2011-2022 走看看