Vertex Covers

时间限制: 5 Sec  内存限制: 128 MB
提交: 5  解决: 3

题目描述

In graph theory, a vertex cover of a graph G is a set of vertices S such that each edge of the graph is incident to at least one vertex of the set. That is to say, for every edge (u,v) of the graph, either u or v is in the vertex cover S.
Now, Kamilah shows you an undirected graph G without loops or multiple edges, each vertex of which has a weight.She can evaluate a vertex cover S of G by the product of weights of all vertices belonging to S.Here, the product of an empty set (of numbers) is defined as 1.
You are asked to calculate the sum of the evaluations described above for all vertex covers of G.

输入

The input contains several test cases, and the first line is a positive integer T indicating the number of test cases which is up to 3600.
For each test case, the first line contains three integers n (1≤n≤36) and m (0≤m≤n(n − 1)/2) which are the number of vertices and the number of edges in the graph G, and q (108≤q≤109 ) which is a prime number for the output.
The second line contains n integers, the i-th of which is the weight of the i-th vertices in G. All weights are in the range of 1 to 109 .
Each of the following m lines contains two integers u and v (1≤u, v≤n) describing an edge between the u-th vertex and the v-th one.
We guarantee that no more than 36 test cases satisfy n > 18.

输出

For each test case, output a line containing Case #x: y, where x is the test case number starting from 1, and y is the remainder of the answer divided by q.

样例输入

2
4 3 998244353
1 1 1 1
1 2
2 3
3 4
4 6 998244353
1 1 1 1
1 2
1 3
1 4
2 3
2 4
3 4

样例输出

Case #1: 8
Case #2: 5

题意:设一个图的点覆盖的贡献是该点覆集中点权的积,求一个图的所有点覆盖的贡献和。
思路(来自题解):

考虑折半,将点集分为大小接近的两部分 L 和 R,那么边集 分为 L 内部的、R 内部的以及 L 和 R 之间的。
枚举 L 的子集 S,检查是否 L 内部所有边都被覆盖。
再枚举 R 的子集 T,检查是否 R 内部所有边都被覆盖,如果是,那么根据 L 和 R 之间的未覆盖边可以知道 L 的一个合法的子集 T′ 必须要覆盖掉当前的未覆盖边,那么可以在 L 内选出所 有包含 T′ 的可行 S,这样 S+T 就是一个 vertex cover。
由于乘法满足分配率,只需要对 S 做一个高维前缀和就能 快速计算答案。

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std; const int N = ;
long long arr[N];
long long pre[<<]={}; unsigned long long Map[N]={}; int check(int x,int l,int r)
{
for(int i=l;i<=r;i++)
{
if(((<<i)&x)==)
{
unsigned long long now=((Map[i]<<(-r))>>(-r));
if((now&x)!=now)return ;
}
}
return ;
} int check2(int x,int l,int r,int mid)
{
for(int i=l;i<=r;i++)
{
if(((<<i)&x)==)
{
long long now=(Map[i+mid]>>mid);
if((now&x)!=now)return ;
}
}
return ;
} int main()
{
int t,Ca=;
scanf("%d",&t); while(t--)
{
int n,m;
long long mod;
scanf("%d %d %lld",&n,&m,&mod); for(int i=;i<n;i++)scanf("%lld",&arr[i]); memset(Map,,sizeof(Map));
while(m--)
{
int u,v;
scanf("%d %d",&u,&v);
u--;
v--;
Map[u]|=1ll<<v;
Map[v]|=1ll<<u;
} int mid=n/; for(int i=(<<mid)-;i>=;i--)pre[i]=; int upper=(<<mid)-; for(int i=;i<=upper;i++)
{
long long sum=;
for(int j=;j<mid;j++)
if((<<j)&i)sum=(sum*arr[j])%mod; if(check(i,,mid-))pre[i]=sum;
} for(int i=;i<mid;i++) //高维后缀和
for(int j=upper;j>=;j--)
if((j&(<<i))==) pre[j]=(pre[j]+pre[j^(<<i)])%mod; upper=(<<(n-mid))-; long long ans=;
for(int i=;i<=upper;i++)
{
long long sum=;
for(int j=;j<n-mid;j++)
if((<<j)&i)sum=(sum*arr[j+mid])%mod; if(check2(i,,n-mid-,mid))
{
long long base=;
for(int x=;x<=mid-;x++)
{
unsigned long long now=(Map[x]>>mid);
if((now&i)!=now)base|=<<x;
}
ans=(ans+sum*pre[base]%mod)%mod;
}
}
printf("Case #%d: %lld\n",Ca++,ans);
}
return ;
}

Vertex Covers(高维前缀和)的更多相关文章

  1. BZOJ.5092.[Lydsy1711月赛]分割序列(高维前缀和)

    题目链接 \(Description\) \(Solution\) 首先处理\(a_i\)的前缀异或和\(s_i\).那么在对于序列\(a_1,...,a_n\),在\(i\)位置处分开的价值为:\( ...

  2. HDU.5765.Bonds(DP 高维前缀和)

    题目链接 \(Description\) 给定一张\(n\)个点\(m\)条边的无向图.定义割集\(E\)为去掉\(E\)后使得图不连通的边集.定义一个bond为一个极小割集(即bond中边的任意一个 ...

  3. SPOJ.TLE - Time Limit Exceeded(DP 高维前缀和)

    题目链接 \(Description\) 给定长为\(n\)的数组\(c_i\)和\(m\),求长为\(n\)的序列\(a_i\)个数,满足:\(c_i\not\mid a_i,\quad a_i\& ...

  4. LOJ2542 PKUWC2018 随机游走 min-max容斥、树上高斯消元、高维前缀和、期望

    传送门 那么除了D1T3,PKUWC2018就更完了(斗地主这种全场0分的题怎么会做啊) 发现我们要求的是所有点中到达时间的最大值的期望,\(n\)又很小,考虑min-max容斥 那么我们要求从\(x ...

  5. Luogu3175 HAOI2015 按位或 min-max容斥、高维前缀和、期望

    传送门 套路题 看到\(n \leq 20\),又看到我们求的是最后出现的位置出现的时间的期望,也就是集合中最大值的期望,考虑min-max容斥. 由\(E(max(S)) = \sum\limits ...

  6. BZOJ5092:[Lydsy1711月赛]分割序列(贪心,高维前缀和)

    Description 对于一个长度为n的非负整数序列b_1,b_2,...,b_n,定义这个序列的能量为:f(b)=max{i=0,1,...,n}((b_1 xor b_2 xor...xor b ...

  7. HihoCoder - 1496:寻找最大值(高维前缀和||手动求子集)

    描述 给定N个数A1, A2, A3, ... AN,小Ho想从中找到两个数Ai和Aj(i ≠ j)使得乘积Ai × Aj × (Ai AND Aj)最大.其中AND是按位与操作. 小Ho当然知道怎么 ...

  8. BZOJ:5092 [Lydsy1711月赛]分割序列(贪心&高维前缀和)

    Description 对于一个长度为n的非负整数序列b_1,b_2,...,b_n,定义这个序列的能量为:f(b)=max{i=0,1,...,n}((b_1 xor b _2 xor...xor ...

  9. BZOJ4036:按位或 (min_max容斥&高维前缀和)

    Description 刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行或(c++,c的|,pascal 的or)操作.选择数字i的概率是p[i].保证0&l ...

随机推荐

  1. MATLAB 去掉数组里面不要的元素

    trainfinger=1 testingfinger=(1:8); testingfinger = testingfinger(~ismember(testingfinger,trainfinger ...

  2. AM8 自定义表情包的实现方法

    AM8 自定义表情包的实现方法 效果描述 AM8 安装后,在\Activesoft\AMm8\emotions 目录内存储的是默认的表情符号.但有的时候我们需要增加一些新的表情符号,AM8 系统支持自 ...

  3. 小程序中template的用法

    demo案例: wxml代码: <view> <text>template使用demo</text> <!-- <view wx:for="{ ...

  4. git归纳总结

    1,git 是分布式版本控制:单个电脑就是一个完整的版本库,只需向中央服务器(远程服务器)提交修改的部分.在没有网络情况下也能正常想本机服务器提交代码管理版本,有网时再推送到远程服务器.   svn是 ...

  5. 廖雪峰Java11多线程编程-3高级concurrent包-5Atomic

    Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int increm ...

  6. C++指针类型间强制转换

    深入理解指针类型间的转换 C++中指针的强制转换 强制类型转换(int).(int&)和(int*)的区别 内存中的地址 地址的本质就是一串0和1的机器代码,内存中的地址没有明确数据类型,但地 ...

  7. 杂项-公司:Google

    ylbtech-杂项-公司:Google 谷歌公司(Google Inc.)成立于1998年9月4日,由拉里·佩奇和谢尔盖·布林共同创建,被公认为全球最大的搜索引擎公司.谷歌是一家位于美国的跨国科技企 ...

  8. jeecms v9库内新增对象的流程及其他技巧

    cms 开发 ———— 库内新增对象 Products 的流程说明及其他技巧 第一步:Entity com.jeecms.cms.entity.assist.base下建立模型基础类BaseCmsPr ...

  9. FormData兼容IE10 360及DWR的异步上传原理

    摘自:https://github.com/henryluki/FormData/blob/master/formdata.js if(!window.FormData) { (function(se ...

  10. 渗透测试入门DVWA 环境搭建

    DVWA是一款渗透测试的演练系统,在圈子里是很出名的.如果你需要入门,并且找不到合适的靶机,那我就推荐你用DVWA. 我们通常将演练系统称为靶机,下面请跟着我一起搭建DVWA测试环境.如果你有一定的基 ...