题目链接

题目描述

给出 \(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. 【SpringCloud】 Eureka

    Eureka 父工程 核心依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=& ...

  2. Federated Learning002

    联邦学习笔记--002 2022.11.26周六 今天学习了联邦学习中又一篇很经典的论文--Federated Machine Learning: Concept and Applications(联 ...

  3. 利用Anaconda3安装tensorflow/keras,并迁移虚拟环境至不能上网的电脑

    利用Anaconda3安装tensorflow/keras,并迁移虚拟环境至不能上网的电脑 下面记录下利用Anaconda安装tensorflow和keras,前前后后也踩了不少坑.并分别在windo ...

  4. hdfs小文件合并

    HDFS small file merge 1.hive Settings There are 3 settings that should be configured before archivin ...

  5. 【技术实战】Vue技术实战【二】

    需求实战一 效果展示 代码展示 <template> <div> <a-table :dataSource="dataSource" :columns ...

  6. XCTF-CGfsb

    考察知识点 PWN.格式化字符串漏洞 题目链接 https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&am ...

  7. 用go语言和正则表达式写的linux危险命令拦截

    需求如下: package main import "fmt" import "regexp" func main() { var s = "cat ...

  8. Angular与AngularJS区别

    简单介绍 目前 Angular 2 到現在 Angular 11 都是十分穩定的改版,不再出現之前 Angular 1.x 到 Angular 2.x 的哀鴻遍野. 因此目前市面上確實同時存在著兩種差 ...

  9. VUE3、ElementPlus 重构若依vue2 表单构建功能

    Vue3 + ElementPlus + Vite 重构 若依Vue2 表单构建功能 若依官方的Vue3 版本发布已经有段时间了,就是这个表单构建功能一直没有安排计划去适配到Vue3! 前段时间公司需 ...

  10. Avalonia 列表拖拽替换

    实现目标,在一个ListBox中选择一个子项进行拖拽到另一个ListBox中,拖拽到某一子项区域进行替换 下面是axaml代码 1 <ListBox 2 Name="consumabl ...