bzoj 4036 集合幂级数

集合幂级数其实就是一种集合到数的映射,并且我们针对集合的一些操作(or and xor and specil or )为这种映射定义运算.其中一些东西可以通过某些手段将其复杂度降低.

还要写一些其他两种.

 1 /**************************************************************
 2     Problem: 4036
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:3584 ms
 7     Memory:13092 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <cmath>
12 #define eps 1e-10
13 #define N 20
14
15 int n, bound;
16 long double f[1<<N];
17
18 int sg( long double x ) { return (x>-eps)-(x<eps); }
19
20 void trans() {
21     for( int i=0; i<n; i++ ) {
22         int ss=bound^(1<<i);
23         f[ss|(1<<i)] += f[ss];
24         for( int s=(ss-1)&ss; s!=ss; s=(s-1)&ss )
25             f[s|(1<<i)] += f[s];
26     }
27 }
28 void inverse() {
29     for( int i=0; i<n; i++ ) {
30         int ss=bound^(1<<i);
31         f[ss|(1<<i)] -= f[ss];
32         for( int s=(ss-1)&ss; s!=ss; s=(s-1)&ss )
33             f[s|(1<<i)] -= f[s];
34     }
35 }
36
37 int main() {
38     scanf( "%d", &n );
39     bound = (1<<n)-1;
40     for( int s=0; s<=bound; s++ )
41         scanf( "%Lf", f+s );
42     trans();
43     for( int s=0; s<=bound; s++ ) {
44         if( sg(f[s]-1)==0 )
45             f[s] = 0;
46         else
47             f[s] = 1/(f[s]-1);
48     }
49     inverse();
50     if( sg(f[bound])==0 )
51         printf( "INF\n" );
52     else
53         printf( "%.10Lf\n", f[bound] );
54 }

时间: 2024-08-07 17:01:01

bzoj 4036 集合幂级数的相关文章

BZOJ 2734 集合选数(状态压缩DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2734 题意:给出一个由1到n的数字组成的集合.定义合法子集为若x在子集中则2x.3x均不能在子集中.求有多少个合法的子集. 思路: 1   3    9 2   6    12 4   12   36 对于上面的矩阵,我们发现就等价于不选相邻数字的方案数.因此枚举每个还没有用到的数字,建立以该数字为左上角的矩阵.接着就是状态压缩DP. int a[N][N]; i64 f[2][1<<

【杂题】[AGC034F] RNG and XOR【集合幂级数】【FWT】【DP】

Description 你有一个随机数生成器,它会以一定的概率生成[0,2^N-1]中的数,每一个数的概率是由序列A给定的,Pi=Ai/sum(Ai) 现在有一个初始为0的数X,每一轮随机生成一个数v,将X变成X xor v 求X变成0~2^N-1的期望轮数 答案对998244353取模 N<=18,Ai<=1000 Solution 不妨反过来做,f[i]为i到0的期望轮数,显然等价 易得i>0, \[f[i]=1+\sum f[i\ xor\ j]p[j]\] 1移到左边来 \[f[

【uoj#94】【集训队互测2015】胡策的统计(集合幂级数)

题目传送门:http://uoj.ac/problem/94 这是一道集合幂级数的入门题目.我们先考虑求出每个点集的连通生成子图个数,记为$g_S$,再记$h_S$为点集$S$的生成子图个数,容易发现,$h_S=2^{size_S}$,其中$size_S$为点集$S$的极大生成子图内的边数.特殊的,$f_{\o}=g_{\o}=0$. 定义集合幂级数的乘法为子集卷积,考虑集合幂级数$h$和$g$的关系,我们可以得到 $$h=1+\sum_{k \geq 1}\frac{g^k}{k!}=1+e^

BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

http://www.lydsy.com/JudgeOnline/problem.php?id=4036 http://blog.csdn.net/lych_cys/article/details/50898726 http://blog.csdn.net/qq_21995319/article/details/49800999 for(int i=1;i<=1;i++) for(int j=1;j<=1;j++) f[i○j]=a[i]*b[j]; 当○为按位或时,这种运算就称为集合并卷积.

BZOJ 2839 集合计数 容斥原理

题目大意:给定n个元素,求交集大小为k的集合的集合共有多少种 考虑容斥原理 计算交集大小至少为i的集合有多少种 首先需要选出i个元素 方案为C(n,i) 其它2^(n-i)个集合每个可选可不选 一共2^[2^(n-i)]种 故答案为Σ[k<=i<=n]C(n,i)C(i,k)*2^[2^(n-i)] #include <cstdio> #include <cstring> #include <iostream> #include <algorithm&

bzoj 4036 [HAOI2015]按位或——min-max容斥+FMT

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4036 题解:https://www.cnblogs.com/Zinn/p/10260126.html #include<cstdio> #include<cstring> #include<algorithm> #define db double using namespace std; const int N=25,M=(1<<20)+5; int

bzoj 4036 按位或 —— min-max容斥+FMT

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4036 min-max容斥:https://blog.csdn.net/ez_2016gdgzoi471/article/details/81416333 二项式反演:https://blog.csdn.net/ez_2016gdgzoi471/article/details/81408416 而出现 \( S \) 的期望,就是 \( S \) 每一位出现的期望中的最大值: 所以 \( E

BZOJ 2734 集合选数

高妙的算法-- 可以构造出形如: 1  2  4   8   16  32 64 3  6  12  24 48 9  18 36 27 54 的矩阵 相邻的数不能被同时选到 因此 将每一个数构造进矩阵 然后状态压缩dp 根据乘法原理 就可以 得出所有的方案 1 #include <bits/stdc++.h> 2 #define mod 1000000001 3 using namespace std; 4 int n,vis[100010],ans,num[23]; 5 int mps[2

BZOJ 4036 [HAOI2015] Set 解题报告

首先我们不能一位一位的考虑,为什么呢? 你想想,你如果一位一位地考虑的话,那么最后就只有 $n$ 个数字,然而他给了你 $2^n$ 个数字,怎么看都不对劲呀.(我是因为这样子弄没过样例才明白的) 所以我们还是要想想其他的方法. 我们是要算步数的期望,然而步数是一个离散的整数,所以我们可以把问题转化一下: $$E(s) = \sum_{k=1}^{\infty}P(s\ge k)$$ 然后就好做了嘛. 我们可以求出一个 $F_i = \sum_{j\subseteq i} p_j$,表示随机选一个