玛里苟斯

一个大小为 \(n\) 的可重集合 \(a\) ,求 \(\mathbb E[x^k]\) ,其中 \(x\) 为 \(a\) 的一个子集的异或和。

\(n\le 10^5,1\le k\le 5\) ,保证答案小于 \(2^{63}\) 。

分析

这题挺妙的呢。

保证答案小于 \(2^{63}\) ,其实是告诉我们,答案的二进制位数 小于 64 位 。这就是说,对于一个 \(k\) ,\(a_i\) 的二进制位数 \(m\) 小于 \(\frac{64}{k}\) 。

首先明确这样一件事情:若 \(a\) 中某一位有 1,那么在所有异或和中,这一位为 1 的占 \(\frac{1}{2}\) 。也就是说,若这一位没有 1,那么所有异或和中这一位的期望为 0,否则为 \(\frac{1}{2}\) 。

这是因为,对于其他元素的所有子集的异或和,异或上这一位与不异或这一位,必定有一个 1 一个 0 ,所以 1 一定占刚好 \(\frac{1}{2}\) 。

令 \(S\) 为 \(n\) 的所有子集的异或和的可重集合,对每一位分开考虑,那就有

\[\begin{aligned}
\text{ans}&=\sum _{s\in S}(\sum_{i=0}^m 2^i[s_i=1])^k \\
&=\sum _{c_1=0}^m\sum _{c_2=0}^m\cdots\sum _{c_k=0}^m\frac{2^{\sum c}}{2^n}\sum _{s\in S}[s_{c_p}=1,p\in [1,k]] \\
&=\sum _{c_1=0}^m\sum _{c_2=0}^m\cdots\sum _{c_k=0}^m2^{\sum c}P(a中c_i位上均为1) \\
&=\sum _{c_1=0}^m\sum _{c_2=0}^m\cdots\sum _{c_k=0}^m2^{\sum c}\frac{[a中c_i位上均有1]}{2^{c_i中不同的个数}} \\
\end{aligned}
\]

最后的形式可以对 \(c\) 中的位建线性基来求。总复杂度为 \(O(m^{k+1}k)=O(64m^{k-1})\) 。

代码

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long giant;
inline char nchar() {
static const int bufl=1<<20;
static char buf[bufl],*a,*b;
return a==b && (b=(a=buf)+fread(buf,1,bufl,stdin),a==b)?EOF:*a++;
}
template<class T> inline T read() {
T x=0;
char c=nchar();
for (;!isdigit(c);c=nchar());
for (;isdigit(c);c=nchar()) x=x*10+c-'0';
return x;
}
const int maxn=1e5+1;
const int maxj=64;
const int maxk=5;
template<typename T> inline void Max(T &x,T y) {x=max(x,y);}
int b[maxk],c[maxk],n,m=0,k;
giant ans=0,a[maxj],s[maxn];
void dfs(int now) {
if (now==k) {
memset(b,0,sizeof b);
int gs=1;
for (int j=m;j>=0;--j) {
int x=0;
for (int i=k;i--;) if ((a[j]>>c[i])&1) x|=1<<i;
for (int i=k;i--;) if ((x>>i)&1) (b[i]?0:(b[i]=x,--gs)),x^=b[i];
}
int x=(1<<k)-1;
for (int i=k;i--;gs+=c[i]) if ((x^b[i])<x) x^=b[i];
if (!x) ans+=1ull<<gs;
return;
}
for (int i=0;i<=m;++i) c[now]=i,dfs(now+1);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read<int>(),k=read<int>();
for (int i=1,j;i<=n;++i) {
giant &x=s[i]=read<giant>();
for (j=maxj;j--;) if ((x>>j)&1) break;
Max(m,j);
}
for (int i=1;i<=n;++i) {
giant x=s[i];
for (int j=m;j>=0 && x;--j) if ((x>>j)&1) (a[j]?0:(a[j]=x)),x^=a[j];
}
dfs(0);
printf("%lld%s\n",ans>>1,ans&1?".5":"");
return 0;
}

主旋律

一个 \(n\) 个点 \(m\) 条边的有向图,问有多少种删边方案使得得到的有向图仍然是一个强连通图。\(n\le 15,m\le n(n-1)\) 。

分析

问题转化为有多少个点集不变的子图是强连通的。

复习一下强连通图计数,即可得到这题的方法——不过是在这个图上进行。

设 \(f(S)\) 为仅包含点集 \(S\) 的 强连通图 个数。

设 \(g(S)\) 为仅包含点集 \(S\) 的 多个(包括 1 个)强连通块组成的图个数,带容斥系数,奇数个连通块加,偶数个连通块减

设 \(h(S)\) 为仅包含点集 \(S\) 的有向图个数。

上述图的边都属于原图的边集。

有以下两条关系式:

\[\begin{aligned}
h(S)&=\sum _{\emptyset \subsetneqq T\subset S} g(T)h(S\setminus T)2^{b(T,S\setminus T)} \\
g(S)&=f(S)-\sum _{\emptyset \subsetneqq T\subsetneqq S} f(T)g(S\setminus T)
\end{aligned}
\]

其中 \(b(A,B)\) 表示 \(|\{(u,v)|,u\in A,v\in B,(u,v)\in E\}|\) 。

这可以用 in[x][s],out[x]][s] 分别表示 \(x\) 到一个集合的边数和集合到 \(x\) 的边数预处理。

预处理的部分会用到莫比乌斯变换,即子集之和。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long giant;
inline int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=15;
const int maxm=maxn*(maxn-1);
const int maxs=1<<maxn;
const int q=1e9+7;
inline int Plus(int x,int y) {return (x+=y)>=q?x-q:x;}
inline void Pe(int &x,int y) {x=Plus(x,y);}
inline int Multi(int x,int y) {return 1ll*x*y%q;}
inline void Me(int &x,int y) {x=Multi(x,y);}
inline int Sub(int x,int y) {return (x-=y)<0?x+q:x;}
inline void Se(int &x,int y) {x=Sub(x,y);}
inline int mi(int x,int y) {
int ret=1;
for (;y;y>>=1,Me(x,x)) if (y&1) Me(ret,x);
return ret;
}
int n,m,S,in[maxn][maxs],out[maxn][maxs],e[maxs],b[maxs],two[maxm+1];
int f[maxs],g[maxs],h[maxs];
struct bian {
int x,y;
} a[maxm];
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
two[0]=1;
for (int i=1;i<=maxm;++i) two[i]=Multi(two[i-1],2);
n=read(),m=read(),S=1<<n;
for (int i=0;i<m;++i) {
int &x=a[i].x=read()-1,&y=a[i].y=read()-1;
++in[y][1<<x],++out[x][1<<y],++e[(1<<x)|(1<<y)];
}
for (int i=0;i<n;++i) for (int j=0;j<n;++j) for (int s=0;s<S;++s) if ((s>>j)&1) Pe(in[i][s],in[i][s^(1<<j)]),Pe(out[i][s],out[i][s^(1<<j)]);
for (int i=0;i<n;++i) for (int s=0;s<S;++s) if ((s>>i)&1) Pe(e[s],e[s^(1<<i)]);
for (int s=1;s<S;++s) h[s]=two[e[s]];
for (int s=1;s<S;++s) { // rig?
for (int t=s;;t=(t-1)&s) {
int &bt=b[t]=0;
if (t==s) continue;
if (!t) break;
int o=s^t,x=__builtin_ctz(o);
bt=Plus(Sub(b[t^(1<<x)],out[x][o^(1<<x)]),in[x][t]);
}
int &gs=g[s]=h[s];
for (int t=s;t;t=(t-1)&s) Se(gs,Multi(Multi(g[t],h[s^t]),two[b[t]]));
}
for (int s=1;s<S;++s) {
int v=__builtin_ctz(s),&fs=f[s]=g[s];
for (int t=(s-1)&s;t;t=(t-1)&s) if ((t>>v)&1) Pe(fs,Multi(f[t],g[s^t]));
}
printf("%d\n",f[S-1]);
return 0;
}

奇数国

简单题,线段树+压位。

清华集训2015-Day 1的更多相关文章

  1. 清华集训2015 V

    #164. [清华集训2015]V http://uoj.ac/problem/164 统计 描述 提交 自定义测试 Picks博士观察完金星凌日后,设计了一个复杂的电阻器.为了简化题目,题目中的常数 ...

  2. 「清华集训2015」V

    「清华集训2015」V 题目大意: 你有一个序列,你需要支持区间加一个数并对 \(0\) 取 \(\max\),区间赋值,查询单点的值以及单点历史最大值. 解题思路: 观察发现,每一种修改操作都可以用 ...

  3. uoj164. 【清华集训2015】V 统计

    坑爹题面:http://uoj.ac/problem/164 正常题面: 对于一个序列支持下列5个操作: 1.区间加x 2.区间减x并与0取max 3.区间覆盖 4.单点查询 5.单点历史最大值查询 ...

  4. UOJ #164. 【清华集训2015】V | 线段树

    题目链接 UOJ #164 题解 首先,这道题有三种询问:区间加.区间减(减完对\(0\)取\(\max\)).区间修改. 可以用一种标记来表示--标记\((a, b)\)表示把原来的值加上\(a\) ...

  5. uoj#158. 【清华集训2015】静态仙人掌

    http://uoj.ac/problem/158 预处理dfs序,询问转为区间1的个数,用可持久化bitset预处理出所有可能的修改对应哪些位置,然后用一个bitset维护当前每个点的状态,修改时可 ...

  6. [清华集训2015 Day2]矩阵变换-[稳定婚姻模型]

    Description 给出一个N行M列的矩阵,保证满足以下性质: M>N. 矩阵中每个数都是 [0,N]中的自然数. 每行中, [1,N]中每个自然数刚好出现一次,其余的都是0. 每列中,[1 ...

  7. [清华集训2015 Day1]主旋律-[状压dp+容斥]

    Description Solution f[i]表示状态i所代表的点构成的强连通图方案数. g[i]表示状态i所代表的的点形成奇数个强连通图的方案数-偶数个强连通图的方案数. g是用来容斥的. 先用 ...

  8. [清华集训2015 Day1]玛里苟斯-[线性基]

    Description Solution 考虑k=1的情况.假设所有数中,第i位为1的数的个数为x,则最后所有的子集异或结果中,第i位为1的个数为$(C_{k}^{1}+C_{k}^{3}+...)$ ...

  9. LOJ 164 【清华集训2015】V——线段树维护历史最值

    题目:http://uoj.ac/problem/164 把操作改成形如 ( a,b ) 表示加上 a 之后对 b 取 max 的意思. 每个点维护当前的 a , b ,还有历史最大的 a , b 即 ...

  10. 2018.07.28 uoj#164. 【清华集训2015】V(线段树)

    传送门 线段树好题. 要求支持的操作: 1.区间变成max(xi−a,0)" role="presentation" style="position: rela ...

随机推荐

  1. Python2.7-stat

    stat模块,用于解释 os.stat(),os.lstat(),os.fstat() 返回的结果,定义了许多表示文件或路径的各个状态的常数和测试各个状态的函数具体参考 官方文档 和 http://w ...

  2. CAN总线学习系列之二——CAN总线与RS485的比较

    CAN总线学习系列之二——CAN总线与RS485的比较 上 一节介绍了一下CAN总线的基本知识,那么有人会问,现在的总线格式很多,CAN相对于其他的总线有什么特点啊?这个问题问的好,所以我想与其它总线 ...

  3. Python基础之公共方法

    公共方法:就是列表,元组,字典,字符串能共同使用的方法: Python内置函数 内置函数罗列 函数 描述 备注 len(item) 计算容器中的元素个数 del(item) 删除变量 del有两种方法 ...

  4. Luogu P1273 有线电视网

    最近写DP写得比较多了 但是POJ上的题目太傻比了而且不想看英文的题面,然后就在Luogu的试炼场里找了一个DP EX专题写了一下(大概3days吧,一天一题差不多) 这是一道比较简单的DP 话说树形 ...

  5. 阿里云OSS不同账号之间的迁移

    目录 一.需求说明 二.Ossimport概述 三.配置运行环境 1.配置jdk环境 2.部署方式 3.下载并部署ossimport 四.修改单机Job的配置文件local_job.cfg 五.执行迁 ...

  6. android全屏

    this.requestWindowFeature( Window.FEATURE_NO_TITLE ); this.getWindow().setFlags(WindowManager.Layout ...

  7. koa2 入门(1)koa-generator 脚手架和 mongoose 使用

    项目地址:https://github.com/caochangkui/demo/tree/koa2-learn 1 构建项目 1.1 安装koa-generator $ npm install -g ...

  8. R绘图 第五篇:绘制散点图(ggplot2)

    ggplot2包中绘制点图的函数有两个:geom_point和 geom_dotplot,当使用geom_dotplot绘图时,point的形状是dot,不能改变点的形状,因此,geom_dotplo ...

  9. java File读取文件始终不存在的问题分析

    先上图: 如图,f1 始终能读到该文件,使用的是绝对路径 f2 却是相对路径. 感觉很奇怪,明明一模一样的代码为什么会产生不同的结果呢? 首先想到的是是不是有什么特殊字符.. 拿到notepad++中 ...

  10. REST-framework快速构建API--初体验

    一.快速上手 1.环境准备 安装restframework,注册app pip install djangorestframework INSTALLED_APPS = [ 'django.contr ...