很裸的子集反演模板题,套上一些莫名其妙的外衣。

先预处理每个集合是否合法,再作显然的状压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)的更多相关文章

  1. UOJ348 WC2018 州区划分 状压DP、欧拉回路、子集卷积

    传送门 应该都会判欧拉回路吧(雾 考虑状压DP:设\(W_i\)表示集合\(i\)的点的权值和,\(route_i\)表示点集\(i\)的导出子图中是否存在欧拉回路,\(f_i\)表示前若干个城市包含 ...

  2. 【UOJ348】【WC2018】州区划分 状压DP FWT

    题目大意 给定一个\(n\)个点的无向图,对于每种 \(n\) 个点的划分\(\{S_1,S_2,\ldots,S_k\}\),定义它是合法的,当且仅当每个点都在其中的一个集合中且对于任何的\(i\i ...

  3. UOJ #348 州区划分 —— 状压DP+子集卷积

    题目:http://uoj.ac/problem/348 一开始可以 3^n 子集DP,枚举一种状态的最后一个集合是什么来转移: 设 \( f[s] \) 表示 \( s \) 集合内的点都划分好了, ...

  4. Luogu4221 WC2018州区划分(状压dp+FWT)

    合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方 ...

  5. 集合划分状压dp

    给一个 $n$ 个点 $m$ 条边的无向图,每条边有 $p_i$ 的概率消失,求图连通的概率 $n \leq 9$ sol: 我们考虑一个 $dp$ $f_{(i,S)}$ 表示只考虑前 $i$ 条边 ...

  6. P4221 [WC2018]州区划分 无向图欧拉回路 FST FWT

    LINK:州区划分 把题目中四个条件进行规约 容易想到不合法当前仅当当前状态是一个无向图欧拉回路. 充要条件有两个 联通 每个点度数为偶数. 预处理出所有状态. 然后设\(f_i\)表示组成情况为i的 ...

  7. [WC2018]州区划分——FWT+DP+FST

    题目链接: [WC2018]州区划分 题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路.对于一种划分方案,第i个部分的 ...

  8. [WC2018]州区划分(FWT,FST)

    [WC2018]州区划分(FWT,FST) Luogu loj 题解时间 经典FST. 在此之前似乎用到FST的题并不多? 首先预处理一个子集是不是欧拉回路很简单,判断是否连通且度数均为偶数即可. 考 ...

  9. [WC2018]州区划分(FWT)

    题目描述 题解 这道题的思路感觉很妙. 题目中有一个很奇怪的不合法条件,貌似和后面做题没有什么关系,所以我们先得搞掉它. 也就是判断一个点集是否合法,也就是判断这个点集是否存在欧拉回路. 如果存在欧拉 ...

随机推荐

  1. H5 键盘兼容性小结

    H5 键盘兼容性小结 在 H5 项目中,我们会经常遇到页面中存在单个甚至多个 input/textarea 输入框与底部固定元素的布局情况.在 input/textarea 输入框获取焦点时,会自动触 ...

  2. 微信web开发者工具无法打开的解决方法

    参考网址:https://blog.csdn.net/gz506840597/article/details/77915488 我试了上面兄弟说的方法还是无效 下面说说我的方法: 我打开文件所在位置, ...

  3. C# 所生成项目的处理器架构“MSIL”与引用“Oracle.DataAccess, Version=4.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86”的处理器架构“x86”不匹配。这种不匹配可能会导致运行时失败。

    这个问题一般都是Oracle.DataAccess的版本不兼容问题造成的. 解决办法: 1.把Oracle.DataAccess.dll文件拿到C盘或D盘的安装文件的地方进行搜索. 2.会出现在pro ...

  4. vue项目中遇到的一些问题

    或访问:https://github.com/littleHiuman/experiences-about-vue  欢迎补充! vuex 状态 vue-cli 命令行 vue vue vue-rou ...

  5. 25 The Go image/draw package go图片/描绘包:图片/描绘包的基本原理

    The Go image/draw package  go图片/描绘包:图片/描绘包的基本原理 29 September 2011 Introduction Package image/draw de ...

  6. SQLAlchemy-对象关系教程ORM-query

    一:对象关系教程查询 一个 Query创建对象时使用 Session的query()方法 .此函数接受一个变量数量的参数,可以是任何类和class-instrumented描述符的组合. Query返 ...

  7. Elasticsearch doc_value认识

    一.doc_value是什么 绝大多数的fields在默认情况下是indexed,因此字段数据是可被搜索的.倒排索引中按照一定顺序存放着terms供搜索,当命中搜索时,返回包含term的documen ...

  8. putIfAbsent

    public static HashSet<Long> getOrInitHashMapCacheValue(Long mId){ // HashSet<Long> set = ...

  9. 20165203《Java程序设计》第九周学习总结

    20165203<Java程序设计>第九周学习总结 教材学习内容总结 URL类 URL类是java.net包中的一个重要的类,URL的实例封装着一个统一资源定位符,使用URL创建对象的应用 ...

  10. Entity Framework Code First 在Object Join Linq查询时出现全表查询的语句。

    最近一个项目,使用微软的Entity Framework的ORM框架的项目,部署到现场后,出现了系统缓慢,多个客户端的内存溢出崩溃的问题. 打开了SQL Server Profiler(SQL Ser ...