题目链接

题目描述

给出 \(n\) 个城市,\(m\) 条边,一个划分合法当且仅当所有划分中的点集和集合中点之间存在的边集所构成的图不构成欧拉回路且联通。

定义一个点集的值为

划分的总值为其中所有点集的值之积,求所有合法划分的值之和。

题目分析

看到数据范围以及题目描述,不难想到使用状压 dp 解决此问题,首先对于每种状态判断是否合法,再枚举当前总状态和最后一个加进来的状态。

设当前状态为 \(i\),枚举出的子集状态为 \(j\),保证其合法,状态集合大小记为 \(siz_i\),可以得到以下状态转移方程:

\(f_i=\sum_{i\bigcap j=j}f_j(\frac{siz_j}{siz_i})^p\)

时间复杂度为 \(O(3^n)\),还无法通过本题。

继续观察柿子,如果把后面的乘数拆开分别处理,一个放到等式左边,一个另起一个函数,就会发现这其实就是一个子集卷积,卷完左边后对于右边部分乘上逆元恢复就行。

还有一个问题,这个柿子中 \(f\) 会自己卷自己,不过发现卷积中只会用到比自己 1 的个数少的状态,只需要一边卷一边处理即可。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#define N 35
#define ll long long
using namespace std;
ll e,head[50000],nex[50000],to[50000];
ll val[N],g[22][(1<<22)];
ll vis[N],f[22][(1<<22)];
ll inv[(1<<22)];
ll n;
const ll mod=998244353;
queue<ll> q;
ll qp(ll x,ll y){
ll ans=1;
while(y){
if(y&1) ans=(ans*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return ans;
}
void add(ll u,ll v){
to[++e]=v;nex[e]=head[u];head[u]=e;
to[++e]=u;nex[e]=head[v];head[v]=e;
}
bool jud(ll x){
if(x==0) return false;
while(q.size()) q.pop();
for(ll i=1;i<=n;i++) vis[i]=0;
for(ll i=1;i<=n;i++)if((1<<(i-1))&x){q.push(i);break;}
while(q.size()){
ll u=q.front();q.pop();if(vis[u])continue;vis[u]++;
for(int i=head[u];i;i=nex[i]){
int v=to[i];
if((1<<(v-1))&x && !vis[v]) q.push(v);
}
}
for(ll i=0;i<n;i++) if((1<<i)&x && !vis[i+1]) return true;
for(ll i=0;i<=n;i++){
if(x&(1<<i)){
int cnt=0;
for(ll j=head[i+1];j;j=nex[j]){
ll v=to[j];
if((1<<(v-1))&x) cnt++;
}
if(cnt%2) return true;
}
}
return false;
}
ll sum(ll x){
ll ans=0;
for(ll i=0;i<n;i++) if(x&(1<<i)) ans+=val[i+1];
return ans;
}
void fwt(ll *f,ll opt){
for(ll mid=1,R=2;R<=(1<<n);R<<=1,mid<<=1){
for(ll j=0;j<(1<<n);j+=R){
for(ll k=0;k<mid;k++){
if(opt==1) f[j+k+mid]=(f[j+k+mid]+f[j+k])%mod;
else f[j+k+mid]=(f[j+k+mid]-f[j+k]+mod)%mod;
}
}
}
}
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int main(){
ll m,p,u,v;
n=read();m=read();p=read();
for(ll i=1;i<=m;i++){
u=read();v=read();
add(u,v);
}
for(ll i=0;i<n;i++) val[i+1]=read();
for(ll i=0;i<(1<<n);i++){
if(jud(i)) g[__builtin_popcount(i)][i]=qp(sum(i),p);
inv[i]=qp(qp(sum(i),mod-2),p);
}
f[0][0]=1;fwt(f[0],1);
for(ll i=0;i<=n;i++) fwt(g[i],1);
for(ll i=1;i<=n;i++){
for(ll j=0;j<i;j++){
for(ll k=0;k<(1<<n);k++){
f[i][k]+=(f[j][k]*g[i-j][k])%mod;
f[i][k]%=mod;
}
}
fwt(f[i],-1);
for(ll j=0;j<(1<<n);j++){
if(__builtin_popcount(j)==i)f[i][j]=(f[i][j]*inv[j])%mod;
else f[i][j]=0;
}
if(i!=n)fwt(f[i],1);
}
cout<<f[n][(1<<n)-1];
}

P4221 [WC2018]州区划分 题解的更多相关文章

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

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

  2. uoj#348/洛谷P4221 [WC2018]州区划分(FWT)

    传送门(uoj) 传送门(洛谷) 全世界都会子集卷积就咱不会--全世界都在写\(FMT\)就咱只会\(FWT\)-- 前置芝士 或运算\(FWT\)或者\(FMT\) 左转洛谷模板区,包教包会 子集卷 ...

  3. [UOJ#348][WC2018]州区划分

    [UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 ...

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

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

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

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

  6. [WC2018]州区划分

    [WC2018]州区划分 注意审题: 1.有序选择 2.若干个州 3.贡献是州满意度的乘积 枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0 存在欧拉回路:每个点都是偶度数,且图连通( ...

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

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

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

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

  9. [WC2018]州区划分(状压,子集卷积)

    [洛谷题面]https://www.luogu.org/problemnew/show/P4221 首先考虑判定一个子图是否合法: (1)连通:并查集判断即可. (2)没有欧拉回路:存在欧拉回路的条件 ...

  10. LOJ2340 [WC2018] 州区划分 【FMT】【欧拉回路】

    题目分析: 这题是WC的题??? 令 $g[S] = (\sum_{x \in S}w_x)^p$ $h[S] = g[S]$如果$S$不是欧拉回路 $d[S] = \frac{f[S]}{g[All ...

随机推荐

  1. 【转载】Linux虚拟化KVM-Qemu分析(十)之virtio驱动

    原文信息 作者:LoyenWang 出处:https://www.cnblogs.com/LoyenWang/ 公众号:LoyenWang 版权:本文版权归作者和博客园共有 转载:欢迎转载,但未经作者 ...

  2. .net 6 winform启动器:调用CMD命令行执行dotnet命令启动.net core程序并将控制台输出日志输出到winform textbox实现实时日志显示

    背景 历史遗留问题,生产车间运行的一个.net core signalr程序使用命令行程序启动,经常由于生产人员误操作将光标停留在控制台上导致程序假死,丢失部分测试数据,车间随便找了一台win10系统 ...

  3. FAQ: ansible playbook 中 tasks 与 handlers 的区别

    ansible自动化运维有两种执行方式,一种是对远程主机批量执行命令,使用ansible命令,直接调用模块加参数执行:另一种是对远程主机批量执行脚本,也是调用模块,但是要把参数按照yanl语法写到一个 ...

  4. shell 代码风格

    以终为始 initramfs_cgz=/srv/initrd/osimage/$os/$os_arch/${os_version%-iso}/$(date +"%Y%m%d").0 ...

  5. KVM 硬盘分区扩容(GPT与MBR两种分区、fdisk 与 growpart两种方法)

    因为认知顺序的原因,之前我都是用fdisk命令手工删除分区表后重建进行扩容,后面才发现可以用growpart命令. 实战建议直接点 AWS EC2 存储空间扩容 跳转过去参考,学习操作可以继续往下看. ...

  6. zabbix 概念 - 主机、主机配置模板

    zabbix 是以"主机"为单位来组织监控项的. 主机(Host)是一个你想要监控的网络实体(物理的,或者虚拟的).它可以是一台物理服务器,一个网络交换机,一个虚拟机或者一些应用. ...

  7. 借助 mkcert 和批处理命令生成局域网证书

    借助 mkcert 和批处理命令生成局域网证书 自动获取ipv4,一键生成很方便 cd /d %~dp0 ipconfig |find "IPv4" > ipv4 set / ...

  8. 没有显示器可用的电脑找IP

    一台在手边没有显示器可用的电脑找IP记录 问题 老大给我一台服务器(在我前面的工位)让我自己玩,但是不知道IP地址,我本来想用自己的显示器连上,结果两个DHMI口试过都没反应,不知道ip地址就没法连上 ...

  9. 【心得】C51单片机_中断

    @ 目录 ①学习单片机中断总思想 ②学习单片机中断总思想 ③学习单片机中断总方法 外部中断 定时计数器中断 串行口中断 ④总结 附 ①学习单片机中断总思想 标题客观的说,学习单片机只需要掌握 I/O ...

  10. 历时数月钻研推流/对比各种流媒体服务程序/PK总结

    1 前言 大量测试下来,网页显示视频流实时性从高到低依次是 webrtc > ws-flv > flv > hls.播放器打开rtsp/rtmp视频流实时性由具体的播放器控制,比如缓 ...