【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 }

猜你喜欢

转载自www.cnblogs.com/myx12345/p/11729736.html