zoukankan      html  css  js  c++  java
  • 『JLOI2016』成绩比较

    『JLOI2016』成绩比较 [* easy]

    给定 (N) 个变量,每个变量有 (M) 个属性,属性 (i) 的值在 ([1,U_i]) 中随机。

    (1) 个变量的所有属性的排名以及给出,然后我们知道恰好有 (K) 个变量满足所有属性都严格小于等于 (1)

    求所有可能的合法情况。答案对 (10^9+7) 取模。

    (N,Mle 100,U_ile 10^9)

    Solution

    方便起见,令 (Nleftarrow N-1),同时令 (R_jleftarrow N+1-R_j) 表示有 (R_j) 名同学分数小于等于他。

    容斥,设 (g_i) 表示至少有 (i) 个变量严格小于等于他。

    那么我们可以直接使用 Dp 来计算 (g_i),那么基础方案数为 (inom{N}{i}),假设属性 (j) 的取值为 (x),那么这 (i) 个变量的取值范围均为 (x),那么对于每个属性对答案的贡献均可以独立乘起来,具体来说形如此:

    [egin{aligned} &inom{N-i}{R_j-i}sum_{x=1}^{U_j}x^{R_j}(U_j-x)^{N-R_j} end{aligned}]

    (o=R_j),不难得到:

    [egin{aligned} &inom{N-i}{o-i}sum_{x=1}^{U_j}x^{o}(U_j-x)^{N-o} \&Rightarrow inom{N-i}{o-i}sum_{x=1}^{U_j}x^{o}sum_j inom{N-o}{j}(-1)^j x^jU_j^{N-o-j} \&Rightarrow inom{N-i}{o-i}sum_j inom{N-o}{j}(-1)^j U_j^{N-o-j}sum_{x=1}^{U_j}x^{o+j} end{aligned}]

    (f(k,x)=sum_{i=1}^x i^k)

    那么不难得到维度 (i) 对答案的贡献为:

    [egin{aligned} &inom{N-i}{o-i}sum_j inom{N-o}{j}(-1)^j U_j^{N-o-j}f(o+j,U_j) end{aligned}]

    显然 (o+j) 的取值范围为 (1sim N),同时不难发现后面的式子与枚举的 (i) 无关,所以可以考虑预处理后式,对于 (j=1,2...M) 均预处理后式称为 (t_j),那么枚举 (i) 之后就可以 (mathcal O(NM)) 的计算答案了。

    我们的瓶颈在于希望得到正整数幂多项式,此时有两种选择:

    1. 拉格朗日插值。
    2. 伯努利数。

    由于我想要复习伯努利数,所以这里又重新进行了推导:

    (S_k(n)=sum_{j=1}^n j^k)

    [egin{aligned} &sum_{k=0} S_k(n)frac{x^k}{k!} \&Rightarrowsum_{k=0}sum_{j=1}^n frac{j^kx^k}{k!} \&Rightarrowsum_{j=1}^n e^{jx} \&Rightarrowfrac{e^{(n+1)x}-e^x}{e^x-1} \&Rightarrowfrac{xe^x}{e^x-1} imes frac{e^{nx}-1}{x} end{aligned}]

    我们设前者的 EGF 序列为 ({B_0,B_1...B_k}),后者为 ({frac{n}{1},frac{n^2}{2}...frac{n^{i+1}}{i+1}})

    于是有 (S_k(n)) 即为:

    [egin{aligned} &sum_{i+j=k}B_iinom{k}{i}frac{n^{k-i+1}}{k-i+1} \&Rightarrow frac{1}{k+1}sum_{i+j=k}B_iinom{k+1}{i}n^{k-i+1} end{aligned}]

    计算 (B_i),然后直接得到多项式。

    接下来,注意到:

    [frac{xe^x}{e^x-1} imes frac{e^x-1}{x}=e^x ]

    所以有 ({B_0,B_1...B_k})({frac{1}{1},frac{1}{2}...frac{1}{i+1}}) 的二项卷积结果为 ({1,1,1...1})

    不难注意到 (B_0=1),所以我们有:

    [B_k=1-sum_{i<k}inom{k}{i}B_ifrac{1}{k-i+1} ]

    [B_k=1-frac{1}{k+1}sum_{i<k}inom{k+1}{i}B_i ]

    复杂度为 (mathcal O(N^2M))

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
    #define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
    #define re register
    #define int long long
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int N = 100 + 5 ; 
    const int P = 1e9 + 7 ;  
    int fpow(int x, int k) {
    	int ans = 1, base = x ;
    	while(k) {
    		if(k & 1) ans = 1ll * ans * base % P ;
    		base = 1ll * base * base % P, k >>= 1 ;
    	} return ans ;
    }
    int n, m, lim, K, U[N], R[N], g[N], h[N], B[N] ;
    int f[N], iv[N], fac[N], inv[N], C[N][N], A[N][N] ; 
    int Get(int x, int k) {
    	int ans = 0, d = 1 ;
    	for(re int i = 0; i <= k + 1; ++ i)
    		ans = (ans + d * A[k][i]) % P, d = d * x % P ;
    	return ans ; 
    }
    signed main()
    {
    	n = gi() - 1, m = gi(), K = gi() ; lim = n + 5 ; 
    	rep( i, 1, m ) U[i] = gi() ; 
    	rep( i, 1, m ) R[i] = gi(), R[i] = n - R[i] + 1 ; 
    	fac[0] = inv[0] = C[0][0] = 1 ; 
    	rep( i, 1, lim ) rep( j, 0, lim ) 
    	C[i][j] = (!j) ? 1 : (C[i - 1][j - 1] + C[i - 1][j]) % P ; 
    	rep( i, 1, lim ) 
    		fac[i] = fac[i - 1] * i % P, inv[i] = fpow(fac[i], P - 2), 
    		iv[i] = fpow( i, P - 2 ) ; 
    	B[0] = 1 ; 
    	rep( i, 1, n ) {
    		int d = 0 ;
    		rep( j, 0, i - 1 ) d = (d + C[i + 1][j] * B[j]) % P ; 
    		d = d * iv[i + 1] % P, B[i] = (1 - d + P) % P ; 
    	}
    	rep( k, 0, n ) rep( i, 0, k ) 
    		A[k][k - i + 1] = C[k + 1][i] * B[i] % P * iv[k + 1] % P ;
    	rep( i, 1, m ) {
    		int o = R[i], ans = 0 ; f[0] = 1 ; 
    		rep( j, 1, n ) f[j] = f[j - 1] * U[i] % P ; 
    		for(re int j = 0; j <= n - o; ++ j) {
    			if(j & 1) ans = (ans - C[n - o][j] * f[n - o - j] % P * Get(U[i], o + j) % P + P) % P ; 
    			else ans = (ans + C[n - o][j] * f[n - o - j] % P * Get(U[i], o + j) % P ) % P ;
    		} h[i] = ans ; 
    	}
    	rep( i, 1, n ) {
    		int ans = C[n][i] ; 
    		rep( j, 1, m ) 
    			if( R[j] < i ) ans = 0 ;
    			else ans = ans * C[n - i][R[j] - i] % P * h[j] % P ; 
    		g[i] = ans ; 
    	}
    	int Ans = 0 ; 
    	rep( i, K, n ) {
    		if((i - K) & 1) Ans = (Ans - g[i] * C[i][K] % P + P) % P ; 
    		else Ans = (Ans + g[i] * C[i][K] % P + P) % P ; 
    	}
    	cout << Ans << endl ; 
    	return 0 ;
    }
    
  • 相关阅读:
    数据加密标准(DES)详解(附源码)
    《ProGit》阅读笔记
    版本管理——Git和SVN的介绍及其优缺点
    jQuery-动画
    ajax与jsonp中的几个封装函数
    关于ajax
    js基础——数组的概念及其方法
    js实现放烟花效果——点击处会从下向上升起烟花
    js实现——鼠标移动时跟随着一连的小图片
    BFC的作用及其应用
  • 原文地址:https://www.cnblogs.com/Soulist/p/13793118.html
Copyright © 2011-2022 走看看