【gym102222K】Vertex Covers(高维前缀和,meet in the middle)

题意:给定一张n点m边的图,点带点权,定义点覆盖的权值为点权之积,问所有点覆盖的权值之和膜q

n<=36, 1<=a[i]<=1e9,1e8<=q<=1e9

思路:n<=36,考虑middle in the middle分成两个点数接近的点集L和R

对于L,枚举其子集S,判断S能否覆盖所有L内部的边,预处理出所有合法的S的超集的贡献

对于R,枚举其子集T,判断T能否覆盖所有R内部的边,如果可以则可以推出L,R之间在确定R中选T的前提下左边至少需要选点集T’,答案即为T的点权之积*T’的超集的点权积之和

对于判断覆盖和根据T推T‘使用了大量位运算加速

需要注意的是如果二进制左右移位可能超边界则要使用ull

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 //typedef pair<ll,ll>P;
 11 #define N  300010
 12 #define M  2000010
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pb push_back
 17 #define pi acos(-1)
 18 #define mem(a,b) memset(a,b,sizeof(a))
 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 21 #define lowbit(x) x&(-x)
 22 #define Rand (rand()*(1<<16)+rand())
 23 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 24 #define ls p<<1
 25 #define rs p<<1|1
 26
 27 const //ll MOD=1e9+7,inv2=(MOD+1)/2;
 28       double eps=1e-6;
 29       int INF=1e9;
 30       int dx[4]={-1,1,0,0};
 31       int dy[4]={0,0,-1,1};
 32
 33       ull s[M];
 34       ll a[N],f[N];
 35
 36 int read()
 37 {
 38    int v=0,f=1;
 39    char c=getchar();
 40    while(c<48||57<c) {if(c==‘-‘) f=-1; c=getchar();}
 41    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 42    return v*f;
 43 }
 44
 45 int isok1(int S,int l,int r)
 46 {
 47     rep(i,l,r)
 48      if(!(S>>i&1))
 49      {
 50          ull now=((s[i]<<(63-r))>>(63-r));
 51          if((now&S)!=now) return 0;
 52      }
 53      return 1;
 54 }
 55
 56 int isok2(int S,int l,int r,int mid)
 57 {
 58     rep(i,l,r)
 59      if(!(S>>i&1))
 60      {
 61         ll now=(s[i+mid]>>mid);
 62         if((now&S)!=now) return 0;
 63      }
 64      return 1;
 65 }
 66
 67 int main()
 68 {
 69     int cas=read();
 70     rep(v,1,cas)
 71     {
 72         int n=read(),m=read();
 73         ll MOD;
 74         scanf("%I64d",&MOD);
 75         int mid=n/2;
 76         rep(i,0,n-1) scanf("%I64d",&a[i]);
 77         mem(s,0);
 78         rep(i,1,m)
 79         {
 80             int x=read(),y=read();
 81             x--; y--;
 82             s[x]|=1ll<<y;
 83             s[y]|=1ll<<x;
 84         }
 85         int S1=(1<<mid)-1;
 86         rep(i,0,S1) f[i]=0;
 87         rep(i,0,S1)
 88         {
 89             ll t=1;
 90             rep(j,0,mid-1)
 91              if(i>>j&1) t=t*a[j]%MOD;
 92             if(isok1(i,0,mid-1)) f[i]=t;
 93         }
 94
 95         rep(i,0,mid-1)
 96          rep(j,0,S1)
 97           if(!(j>>i&1)) f[j]=(f[j]+f[j^(1<<i)])%MOD;
 98
 99         int S2=(1<<(n-mid))-1;
100         ll ans=0;
101         rep(i,0,S2)
102         {
103             ll t=1;
104             rep(j,0,n-mid-1)
105              if(i>>j&1) t=t*a[j+mid]%MOD;
106             if(isok2(i,0,n-mid-1,mid))
107             {
108                 ll base=0;
109                 rep(j,0,mid-1)
110                 {
111                     ull now=(s[j]>>mid);
112                     if((now&i)!=now) base|=1<<j;
113                 }
114                 ans=(ans+t*f[base]%MOD)%MOD;
115             }
116         }
117         printf("Case #%d: ",v);
118         printf("%I64d\n",ans);
119     }
120     return 0;
121 }

原文地址:https://www.cnblogs.com/myx12345/p/11729736.html

时间: 2024-08-30 16:38:32

【gym102222K】Vertex Covers(高维前缀和,meet in the middle)的相关文章

4.7-4.9补题+水题+高维前缀和

题目链接:51nod 1718 Cos的多项式  [数学] 题解: 2cosx=2cosx 2cos2x=(2cosx)^2-2 2cos3x=(2cosx)^3-3*(2cosx) 数归证明2cos(nx)能表示成关于2cosx的多项式,设为f(n) f(1)=x,f(2)=x^2-2(其中的x就是2cosx) 假设n=1~k时均成立(k>=3) 当n=k+1时 由cos((k+1)x)=cos(kx)cos(x)-sin(kx)sin(x) cos((k-1)x)=cos(kx)cos(x)

hihocoder1496(高维前缀和)

题意:给定N个数A1, A2, A3, ... AN,小Ho想从中找到两个数Ai和Aj(i ≠ j)使得乘积Ai × Aj × (Ai AND Aj)最大.其中AND是按位与操作. 第一行一个整数N(1<=N<=100,000) 第二行N个整数A1, A2, A3, ... AN (0 <= Ai <2^20) 分析: 尝试枚举and值z,那么问题就变成了找寻最大的x*y,使得x&y==z 把这个要求放宽一点,我们来寻找z是x&y子集的情况(这样肯定不会丢掉整体最优

Codeforces 449D:Jzzhu and Numbers(高维前缀和)

[题目链接] http://codeforces.com/problemset/problem/449/D [题目大意] 给出一些数字,问其选出一些数字作or为0的方案数有多少 [题解] 题目等价于给出一些集合,问其交集为空集的方案数, 我们先求交集为S的方案数,记为dp[S],发现处理起来还是比较麻烦, 我们放缩一下条件,求出交集包含S的方案数,记为dp[S], 我们发现dp[S],是以其为子集的方案的高维前缀和, 我们逆序求高维前缀和即可,之后考虑容斥,求出交集为0的情况, 我们发现这个容斥

SPOJ Time Limit Exceeded(高维前缀和)

[题目链接] http://www.spoj.com/problems/TLE/en/ [题目大意] 给出n个数字c,求非负整数序列a,满足a<2^m 并且有a[i]&a[i+1]=0,对于每个a[i],要保证a[i]不是c[i]的倍数, 求这样的a[i]序列的个数 [题解] 我们用dp[i]表示以i为结尾的方案数, 我们发现要满足a[i]&a[i+1]=0,则dp[i]是从上一次结果中所有满足i&j=0的地方转移过来的 i&j=0即i&(~j)=i,即i为~

codeforces 938F(dp+高维前缀和)

题意: 给一个长度为n的字符串,定义$k=\floor{log_2 n}$ 一共k轮操作,第i次操作要删除当前字符串恰好长度为$2^{i-1}$的子串 问最后剩余的字符串字典序最小是多少? 分析: 首先很容易得到一个性质,那就是删除的那些串是可以不交叉的 很容易想到一个很简单的dp dp[i][j]表示考虑原串的前i位,删除状态为j的情况下字典序最小的字符串(注意dp里面保存的是个字符串) 那么很明显就是个O(n^3logn)的dp,无法通过 dp里是一个字符串这个东西是很浪费时间而且很不优美的

[2018.6.21集训]走路-分块高维前缀和-Pollard-Rho

题目大意 给一棵树,每个节点有一个权值$val$. 如果两个点$a$和$b$满足$a$为$b$的祖先且$val[b]$为$val[a]$的约数,那么可以从$a$一步跳到$b$. 求从$1$号节点走到各每个节点的路径数. $n \leq 10^5 , val[i] \leq 10^{18},$保证对于任意节点$i$,$val[i]$为$val[1]$的约数. 题解 首先有定理:一个数$n$的约数个数大概是$n^{\frac{1}{3}}$的级别 然后得到有理有据的一个部分分($val[i] \le

高维前缀和

我们经常要用到前缀和. 一维: for(int i=1;i<=n;i++) b[i]=b[i-1]+a[i]; 二维: for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j]; 那如果是三维的呢? for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=1;k<=p;k++) b[i][j][

bzoj 5092 分割序列 —— 高维前缀和

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5092 首先,处理出异或前缀和 s[i],i 位置的答案就是 s[j] + s[j]^s[i],j <= i 异或的套路是按位考虑,但是这里有加法...怎么考虑进位? 所以就不能考虑答案的这一位是什么,而应该考虑在这一位上的贡献,那么即使进位了,还是各位算各位的贡献,互相独立: 然后发现,如果 s[i] 在第 k 位上是1,那么 s[j] 的第 k 位无论是0还是1,总体的贡献都是 1<&

bzoj 5092 [Lydsy1711月赛]分割序列——高维前缀和

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5092 套路地弄一个前缀异或和,就变成 f[ i ]=max_{j=0}^{i} { s[ j ] + (s[ i ]^s[ j ]) }.再套路地考虑按位贪心. 然后看了题解.按位贪心不是确定 f[ i ] 的这一位是0还是1,而是确定这一位是否给答案贡献 bin[ j ] ! 按位考虑,自己这一位如果是1,则 j 不管取在哪,都只有一种情况,就是向答案贡献 bin[ j ]: 自己这一位

CF449D Jzzhu and Numbers 高维前缀和

title CF449D Description 给出一个长度为 \(n\) 的序列 \(a_1,a_2...a_n\) . 求构造出一个序列 \(i_1 \le i_2 \le ... \le i_k\) 使得 \(a_{i_1}\&a_{i_2}\&...\&a_{i_k}=0\) .求方案数模 \(10^9+7\) . 也就是从 \(\{a_i\}\) 里面选出一个非空子集使这些数按位与起来为 \(0\) . analysis 这不是普转提的第四题吗?不得不防啊. 这也是一个