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

  考虑状压dp。设f[S]为S集合所有划分方案的满意度之和,枚举子集转移,则有f[S]=Σg[S']*f[S^S']*(sum[S']/sum[S])(S'⊆S),其中g[S]为S集合是否合法,sum[S]为S集合人口数之和。复杂度O(3n)。这个式子非常显然,就这么送了50分。p这么小显得非常奇怪但也没有任何卵用。

  考虑优化。转移方程写的更优美一点大约是f[S]=Σf[x]*g[y]/h[S] (x|y=S,x&y=0)。看起来像是一个或卷积,但还有后面一个限制。考虑在x|y=S的前提下,x&y=0实际上相当于|x|+|y|=|S|。于是稍微改一下状态,f[i][S]为i个点所选点集为S时的满意度之和(虽然第一维显然是可以由第二维推出的),g同样更改状态,这样转移就是f[i][S]=Σf[u][x]*g[v][y]/h[S] (x|y=S,u+v=i)。暴力枚举第一维u,FWT做或卷积即可,复杂度O(2n·n2)。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 21
#define P 998244353
#define rep(i,t,S) for (int t=S,i=lg2[t&-t];t;t^=t&-t,i=lg2[t&-t])
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,p,a[N][N],w[N],fa[N],degree[N],lg2[<<N],sum[<<N],size[<<N],f[N+][<<N],g[N+][<<N];
int ksm(int a,int k)
{
int s=;
for (;k;k>>=,a=1ll*a*a%P) if (k&) s=1ll*s*a%P;
return s;
}
int inv(int a){return ksm(a,P-);}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
void get()
{
for (int i=;i<n;i++) lg2[<<i]=i;
for (int i=;i<(<<n);i++)
{
sum[i]=sum[i^(i&-i)]+w[lg2[i&-i]];
size[i]=size[i^(i&-i)]+;
rep(x,u,i) fa[x]=x,degree[x]=;
rep(x,u,i)
{
rep(y,v,i) if (a[x][y]) degree[x]^=,fa[find(x)]=find(y);
if (degree[x]) {g[size[i]][i]=;break;}
}
int f=-;
rep(x,u,i) if (f==-) f=find(x);else if (f!=find(x)) {g[size[i]][i]=;break;}
}
for (int i=;i<(<<n);i++) sum[i]=ksm(sum[i],p),g[size[i]][i]*=sum[i];
}
void FWT(int *a,int n,int op)
{
for (int i=;i<=n;i<<=)
for (int j=;j<n;j+=i)
for (int k=j;k<j+(i>>);k++)
if (!op) a[k+(i>>)]=(a[k+(i>>)]+a[k])%P;
else a[k+(i>>)]=(a[k+(i>>)]-a[k]+P)%P;
}
void solve()
{
f[][]=;
FWT(f[],<<n,);
for (int i=;i<=n;i++) FWT(g[i],<<n,);
for (int i=;i<=n;i++)
{
for (int j=;j<(<<n);j++)
for (int x=;x<i;x++)
f[i][j]=(f[i][j]+1ll*f[x][j]*g[i-x][j])%P;
FWT(f[i],<<n,);
for (int j=;j<(<<n);j++)
if (size[j]==i) f[i][j]=1ll*f[i][j]*inv(sum[j])%P;
FWT(f[i],<<n,);
}
FWT(f[n],<<n,);
cout<<f[n][(<<n)-];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read(),p=read();
for (int i=;i<=m;i++)
{
int x=read()-,y=read()-;
a[x][y]=a[y][x]=;
}
for (int i=;i<n;i++) w[i]=read();
get();
solve();
return ;
}

Luogu4221 WC2018州区划分(状压dp+FWT)的更多相关文章

  1. [WC2018]州区划分(状压DP+FWT/FMT)

    很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...

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

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

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

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

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

    题目:http://uoj.ac/problem/348 一开始可以 3^n 子集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. omcat+java的web程序持续占cpu高问题调试【转】

    1.top -c 2.查看具体线程 ps -m -p 30997 -o tid,%cpu,%mem > threads.log 3.printf %x 31865 其次将需要的线程ID转换为16 ...

  2. 7-51单片机ESP8266学习-AT指令(8266TCP服务器,编写自己的C#TCP客户端发信息给单片机控制小灯的亮灭)

    http://www.cnblogs.com/yangfengwu/p/8780182.html 自己都是现做现写,如果想知道最终实现的功能,请看最后 先把源码和资料链接放到这里 链接: https: ...

  3. grep配置颜色显示

    查日志时候必须要用的命令,为了在终端方便显示查看,可以加颜色和高亮等设置. 自己习惯用的: GREP_COLOR='a;b'  a=4表示下划线,b=41表示红色背景高亮 在~/.bashrc文件中加 ...

  4. linux安装jdk与配置-centos7版本

    1.Linux安裝jdk 1.如果電腦沒有wget命令的,先使用yum安裝wget命令. eg: yum install wget 2.安裝好后就可以直接使用wget命令去下載jdk. 附:打開官網連 ...

  5. 创建一个宽高成比例的弹性div盒子

    这里先提供一种,有更好的方法再补充. demo代码如下: <!DOCTYPE html> <html lang="en"> <head> < ...

  6. MySQL数据库服务器(YUM)安装

    1. 概述2. 部署过程2.1 虚拟机console的NFS服务端配置2.2 虚拟机node15的NFS客户端配置2.3 虚拟机安装MySQL环境2.4 配置MySQL3. 错误及解决3.1 启动失败 ...

  7. NTP服务部署和测试

    1. 概述2. 部署3. 配置4. 客户端配置4.1 客户端安装ntpdate4.2 同步设置 1. 概述 本篇博客主要记录如何部署一台NTP服务器,用于内网时间同步. 时间服务器对于集群内部节点之间 ...

  8. CrackMe005-下篇 | 逆向破解分析 | 160个CrackMe(视频+图文)深度解析系列

    作者:逆向驿站微信公众号:逆向驿站知乎:逆向驿站 CrackMe005,上篇说了具体方法,下篇来发逆向分析过程,看看老夫是如何得到上篇的具体方法的! 准备 [环境和工具] win7/xp虚拟机环境 C ...

  9. Python-文件操作—_19

    1,文件操作 模特主妇护士老师.txt 1,文件路径:d:\模特主妇护士老师.txt 2,编码方式:utf-8 gbk .... 3,操作方式:只读,只写,追加,读写,写读..... 以什么编码方式储 ...

  10. ThiNet: A Filter Level Pruning Method for Deep Neural Network Compression笔记

    前言 致力于滤波器的剪枝,论文的方法不改变原始网络的结构.论文的方法是基于下一层的统计信息来进行剪枝,这是区别已有方法的. VGG-16上可以减少3.31FLOPs和16.63倍的压缩,top-5的准 ...