[WC2018]州区划分(状压DP+FWT/FMT)
很裸的子集反演模板题,套上一些莫名其妙的外衣。
先预处理每个集合是否合法,再作显然的状压DP。然后发现可以写成子集反演的形式,直接套模板即可。
子集反演可以看这里。
子集反演的过程就是多设一维代表集合大小,再FMT处理集合并卷积。
然而我的FMT常数过大,而并卷积又可以用FWT实现,于是就写FWT了。(实际上就三行的区别)
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=,mod=;
int n,m,p,x,y,mp[N][N],w[N],fa[N],a[N],d[N],sm[<<N],sz[<<N],lg[<<N],f[N][<<N],g[N][<<N]; int pow(int a,int b){ return b== ? : (b== ? a : 1ll*a*a%mod); }
int get(int x){ return (fa[x]==x) ? x : fa[x]=get(fa[x]); } int ksm(int a,int b){
int res=;
for (; b; a=1ll*a*a%mod,b>>=)
if (b & ) res=1ll*res*a%mod;
return res;
} void init(){
rep(i,,n) lg[<<i]=i;
rep(S,,(<<n)-){
int t=S&-S,tot=;
sm[S]=sm[S^t]+w[lg[t]]; sz[S]=sz[S^t]+;
for (int i=S; i; i=i^(i&-i)) a[++tot]=lg[i&-i];
rep(i,,tot) fa[a[i]]=a[i],d[a[i]]=;
rep(i,,tot){
rep(j,,tot) if (mp[a[i]][a[j]]) d[a[i]]^=,fa[get(a[i])]=get(a[j]);
if (d[a[i]]) { g[sz[S]][S]=; break; }
}
int f=get(a[]);
rep(i,,tot) if (f!=get(a[i])){ g[sz[S]][S]=; break; }
}
rep(i,,(<<n)-) sm[i]=pow(sm[i],p),g[sz[i]][i]=1ll*g[sz[i]][i]*sm[i]%mod;
} void FMT(int a[],int n,int f){
for (int i=; i<n; i<<=)
rep(j,,n-) if (j&i) a[j]=(a[j]+1ll*f*a[j^i]+mod)%mod;
} void solve(){
f[][]=; FMT(f[],<<n,);
rep(i,,n) FMT(g[i],<<n,);
rep(i,,n){
rep(j,,(<<n)-) rep(x,,i-)
f[i][j]=(f[i][j]+1ll*f[x][j]*g[i-x][j])%mod;
FMT(f[i],<<n,-);
rep(j,,(<<n)-)
if (sz[j]==i) f[i][j]=1ll*f[i][j]*ksm(sm[j],mod-)%mod; else f[i][j]=;
FMT(f[i],<<n,);
}
FMT(f[n],<<n,-); printf("%d\n",f[n][(<<n)-]);
} int main(){
scanf("%d%d%d",&n,&m,&p);
rep(i,,m) scanf("%d%d",&x,&y),mp[x-][y-]=mp[y-][x-]=;
rep(i,,n-) scanf("%d",&w[i]);
init(); solve();
return ;
}
FMT(TLE)
FWT:
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=,mod=;
int n,m,p,x,y,mp[N][N],w[N],fa[N],a[N],d[N],sm[<<N],sz[<<N],lg[<<N],f[N][<<N],g[N][<<N]; int pow(int a,int b){ return b== ? : (b== ? a : 1ll*a*a%mod); }
int get(int x){ return (fa[x]==x) ? x : fa[x]=get(fa[x]); } int ksm(int a,int b){
int res=;
for (; b; a=1ll*a*a%mod,b>>=)
if (b & ) res=1ll*res*a%mod;
return res;
} void init(){
rep(i,,n) lg[<<i]=i;
rep(S,,(<<n)-){
int t=S&-S,tot=;
sm[S]=sm[S^t]+w[lg[t]]; sz[S]=sz[S^t]+;
for (int i=S; i; i=i^(i&-i)) a[++tot]=lg[i&-i];
rep(i,,tot) fa[a[i]]=a[i],d[a[i]]=;
rep(i,,tot){
rep(j,,tot) if (mp[a[i]][a[j]]) d[a[i]]^=,fa[get(a[i])]=get(a[j]);
if (d[a[i]]) { g[sz[S]][S]=; break; }
}
int f=get(a[]);
rep(i,,tot) if (f!=get(a[i])){ g[sz[S]][S]=; break; }
}
rep(i,,(<<n)-) sm[i]=ksm(sm[i],p),g[sz[i]][i]=1ll*g[sz[i]][i]*sm[i]%mod;
} void FWT(int a[],int n,int f){
for (int i=; i<=n; i<<=)
for (int j=; j<n; j+=i)
rep(k,j,j+(i>>)-)
a[k+(i>>)]=(1ll*a[k+(i>>)]+f*a[k]+mod)%mod;
} void solve(){
f[][]=; FWT(f[],<<n,);
rep(i,,n) FWT(g[i],<<n,);
rep(i,,n){
rep(j,,(<<n)-) rep(x,,i-)
f[i][j]=(f[i][j]+1ll*f[x][j]*g[i-x][j])%mod;
FWT(f[i],<<n,-);
rep(j,,(<<n)-)
if (sz[j]==i) f[i][j]=1ll*f[i][j]*ksm(sm[j],mod-)%mod; else f[i][j]=;
FWT(f[i],<<n,);
}
FWT(f[n],<<n,-); printf("%d\n",f[n][(<<n)-]);
} int main(){
scanf("%d%d%d",&n,&m,&p);
rep(i,,m) scanf("%d%d",&x,&y),mp[x-][y-]=mp[y-][x-]=;
rep(i,,n-) scanf("%d",&w[i]);
init(); solve();
return ;
}
[WC2018]州区划分(状压DP+FWT/FMT)的更多相关文章
- UOJ348 WC2018 州区划分 状压DP、欧拉回路、子集卷积
传送门 应该都会判欧拉回路吧(雾 考虑状压DP:设\(W_i\)表示集合\(i\)的点的权值和,\(route_i\)表示点集\(i\)的导出子图中是否存在欧拉回路,\(f_i\)表示前若干个城市包含 ...
- 【UOJ348】【WC2018】州区划分 状压DP FWT
题目大意 给定一个\(n\)个点的无向图,对于每种 \(n\) 个点的划分\(\{S_1,S_2,\ldots,S_k\}\),定义它是合法的,当且仅当每个点都在其中的一个集合中且对于任何的\(i\i ...
- UOJ #348 州区划分 —— 状压DP+子集卷积
题目:http://uoj.ac/problem/348 一开始可以 3^n 子集DP,枚举一种状态的最后一个集合是什么来转移: 设 \( f[s] \) 表示 \( s \) 集合内的点都划分好了, ...
- Luogu4221 WC2018州区划分(状压dp+FWT)
合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方 ...
- 集合划分状压dp
给一个 $n$ 个点 $m$ 条边的无向图,每条边有 $p_i$ 的概率消失,求图连通的概率 $n \leq 9$ sol: 我们考虑一个 $dp$ $f_{(i,S)}$ 表示只考虑前 $i$ 条边 ...
- P4221 [WC2018]州区划分 无向图欧拉回路 FST FWT
LINK:州区划分 把题目中四个条件进行规约 容易想到不合法当前仅当当前状态是一个无向图欧拉回路. 充要条件有两个 联通 每个点度数为偶数. 预处理出所有状态. 然后设\(f_i\)表示组成情况为i的 ...
- [WC2018]州区划分——FWT+DP+FST
题目链接: [WC2018]州区划分 题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路.对于一种划分方案,第i个部分的 ...
- [WC2018]州区划分(FWT,FST)
[WC2018]州区划分(FWT,FST) Luogu loj 题解时间 经典FST. 在此之前似乎用到FST的题并不多? 首先预处理一个子集是不是欧拉回路很简单,判断是否连通且度数均为偶数即可. 考 ...
- [WC2018]州区划分(FWT)
题目描述 题解 这道题的思路感觉很妙. 题目中有一个很奇怪的不合法条件,貌似和后面做题没有什么关系,所以我们先得搞掉它. 也就是判断一个点集是否合法,也就是判断这个点集是否存在欧拉回路. 如果存在欧拉 ...
随机推荐
- python面向对象——类
from:http://www.runoob.com/python3/python3-class.html Python3 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在P ...
- Maven仓库国内镜像站
感谢阿里巴巴,搭建并公开了Maven仓库的国内镜像站.话外:使用Maven的官方仓库真的是太slow了! 在<Maven Root>/conf/settings.xml中的<mirr ...
- 【Python学习笔记】使用python进行kmeans聚类
使用python进行kmeans聚类 假设我们要解决一个这样的问题. 以下是一些同学,大萌是一个学霸,而我们想要找到这些人中的潜在学霸,所以我们要把这些人分为两类--学霸与非学霸. 高数 英语 Pyt ...
- iOS开发之删除Provisioning Profiles方法
1.在finder下打开go -> go to folder输入: ~/Library/MobileDevice/Provisioning Profiles 2.查看上面的列表,按照时间顺序删除 ...
- 30 C? Go? Cgo!
C? Go? Cgo! 17 March 2011 Introduction Cgo lets Go packages call C code. Given a Go source file writ ...
- 26 About the go command go命令行
About the go command go命令行 Motivation Configuration versus convention Go's conventions Getting star ...
- React 学习二 组件
React的一个最大的特点就是组件化的开发模式.今天就来试一下: <!DOCTYPE html> <html> <head> <meta charset=&q ...
- No.16 selenium学习之路之异常处理
一.常见的几种异常: SyntaxError:语法错误 NameError:试图访问的变量名不存在 IndexError:索引错误,使用的索引不存在,超出序列范围 KeyError:使用了不存在的关键 ...
- INSTEAD OF与AFTER触发器
INSTEAD OF 触发器 AFTER 触发器(也叫“FOR”触发器)会在触发 insert.update 或是delect 动作之后执行.例如,一个 Employees 表上的 AFTER 触发器 ...
- 【TensorFlow】一文弄懂CNN中的padding参数
在深度学习的图像识别领域中,我们经常使用卷积神经网络CNN来对图像进行特征提取,当我们使用TensorFlow搭建自己的CNN时,一般会使用TensorFlow中的卷积函数和池化函数来对图像进行卷积和 ...