• [LOJ #6433]「PKUSC2018」最大前缀和


    题目大意:给你一个$n(nleqslant20)$项的数列$A$,设重排后的数列为$A'$,令$pre_p=sumlimits_{i=1}^pA'_i$,求$max{pre_i}$的期望,乘$n!$

    题解:令$f_S$为选$S$集合的数,重排后满足$max{pre_i}=sumlimits_{i=1}^{|S|}S_i$的方案数,$g_S$为选$S$集合数,重排后满足$max{pre_i}leqslant0$的方案数。发现若数列$B$满足$sumlimits_{i=1}^{|B|}B_i>0$,那么任意在它前面插入一个数,都满足$f$的条件。若数列$B$满足$max{pre_i}leqslant0$,在它后面插入一个数后,只要$sumlimits_{i=1}^{|B|}B_ileqslant0$,就行了。

    答案是$sumlimits_{S}sum_Sf_Sg_{ar S}$。

    卡点:

    C++ Code:

    #include <cstdio>
    #define maxn 20
    #define N (1 << maxn)
    const int mod = 998244353;
    inline void reduce(int &x) { x += x >> 31 & mod; }
    
    int n;
    int s[maxn], f[N], g[N], sum[N];
    int main() {
    	scanf("%d", &n);
    	for (int i = 0; i < n; ++i) {
    		scanf("%d", s + i);
    		f[1 << i] = 1;
    		g[1 << i] = s[i] <= 0;
    	}
    	const int U = 1 << n, I = U - 1;
    	for (int i = 1; i < U; ++i) sum[i] = sum[i & i - 1] + s[__builtin_ctz(i)];
    	g[0] = 1;
    	for (int i = 0; i < U; ++i) if (__builtin_popcount(i) > 1) {
    		for (int j = i; j; j &= j - 1) {
    			int k = __builtin_ctz(j), l = i ^ 1 << k;
    			if (sum[i] <= 0) reduce(g[i] += g[l] - mod);
    			if (sum[l] > 0) reduce(f[i] += f[l] - mod);
    		}
    	}
    	for (int i = 0; i < U; ++i) reduce(sum[i] %= mod);
    	int ans = 0;
    	for (int i = 1; i < U; ++i) reduce(ans += static_cast<long long> (sum[i]) * f[i] % mod * g[I ^ i] % mod - mod);
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

  • 相关阅读:
    转载:Android SQLite数据库版本升级原理解析
    Android可移动的Button
    Android详细目录结构
    自动化测试(二)
    不使用if else
    C# 如何实现自己的FormEditor XML Protocol
    C#中的析构函数,GC和IDisposable的用法
    Java中生成和解析JSON
    GCMS笔记
    Android ConstraintLayout的使用(二)
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10300594.html
Copyright © 2020-2023  润新知