uoj348【WC2018】州区划分
题目链接
直接讲吨吨吨给的标准做法吧。记\(f(i,j)\)表示各个州(可以重叠)的城市数量之和为i,这些州的并集为j的方案数,反正若有两个州之间有交集最后的\(|j|\)会不等于\(i\)。有
\(f(i,s)=\sum_{s1} \sum_{s2}[s1|s2==s] \ f(i-|s2|,s1)*can(s2) (\frac{vals(s2)}{vals(s)})^p\)
\(f(i,s)*vals(s)^p=\sum_j \sum_{|s2|=j} \sum_{s1} [s1|s2==s]\ f(i-j,s1)*can(s2) *vals(s2)^p\)
记\(g(|s|,s)\)表示\(can(s)*vals(s)^p\),先在最开始DWT所有的g,枚举i,j,然后卷一下\(f_{i-j}\)与\(g_j\),只要在dp的过程中一直保持f是已经DWT了的,卷积的复杂度就只有\(O(2^n)\),记得\(f_i\)算完以后要IDWT一下乘上\(vals(s)^{-p}\)再DWT。复杂度\(O(n^22^n)\)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#define P puts("lala")
#define cp cerr<<"lala"<<endl
#define ln putchar('\n')
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
inline int read()
{
char ch=getchar();int g=1,re=0;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
return re*g;
}
typedef long long ll;
typedef pair<int,int> pii;
const int N=25;
const int mod=998244353;
inline ll qpow(ll a,int n)
{
ll ans=1;
for(;n;n>>=1,a=a*a%mod) if(n&1) ans=ans*a%mod;
return ans;
}
void FWT(int *a,int n,ll f)
{
for(int step=1;step<n;step<<=1)
for(int j=0;j<n;j+=(step<<1))
for(int k=j;k<j+step;++k)
{
int x=a[k],y=a[k+step];
a[k+step]=(y+f*x+mod)%mod;
}
}
int head[N],cnt=0;
struct node
{
int to,next;
}e[N*N];
inline void add(int x,int y)
{
e[++cnt]=(node){y,head[x]}; head[x]=cnt;
e[++cnt]=(node){x,head[y]}; head[y]=cnt;
}
int val[N],n,m,vals[1<<21|1],deg[N],fa[N];
bool can[1<<21|1];
pii edg[N*N];
inline int find(int x)
{
if(fa[x]!=x) return fa[x]=find(fa[x]);
return fa[x];
}
int f[23][1<<21|1],g[23][1<<21|1];
void wj()
{
#ifndef ONLINE_JUDGE
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
#endif
}
int main()
{
wj();
n=read(); m=read(); int p=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
add(x,y);
edg[i]=pii(x,y);
}
for(int i=1;i<=n;++i) val[i]=read();
int tot=1<<n;
for(int s=0;s<tot;++s)
{
int all=0;
for(int i=1;i<=n;++i) if(s&(1<<i-1)) vals[s]+=val[i],all++;
vals[s]=qpow(vals[s],p);
for(int i=1;i<=n;++i) fa[i]=i,deg[i]=0;
for(int i=1;i<=m;++i) if((s&(1<<edg[i].fi-1))&&(s&(1<<edg[i].se-1)))
{
deg[edg[i].fi]++; deg[edg[i].se]++;
int r1=find(edg[i].fi),r2=find(edg[i].se);
if(r1!=r2) all--;
fa[r1]=r2;
}
can[s]=1;
if(all!=1) continue;
for(int i=1;i<=n;++i) if(s&(1<<i-1))
if(deg[i]&1) {can[s]=1;break;}
else can[s]=0;
}
f[0][0]=1;
for(int s=0;s<tot;++s)
g[__builtin_popcount(s)][s]=can[s]*vals[s],vals[s]=qpow(vals[s],mod-2);
FWT(f[0],tot,1);
for(int i=1;i<=n;++i) FWT(g[i],tot,1);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=i;++j)
{
for(int k=0;k<tot;++k) f[i][k]=(f[i][k]+1ll*f[i-j][k]*g[j][k])%mod;
}
if(!p) continue;
FWT(f[i],tot,-1);
for(int k=0;k<tot;++k) f[i][k]=1ll*f[i][k]*vals[k]%mod;
FWT(f[i],tot,1);
}
FWT(f[n],tot,-1);
printf("%d\n",f[n][tot-1]);
return 0;
}
uoj348【WC2018】州区划分的更多相关文章
- UOJ348 WC2018 州区划分 状压DP、欧拉回路、子集卷积
传送门 应该都会判欧拉回路吧(雾 考虑状压DP:设\(W_i\)表示集合\(i\)的点的权值和,\(route_i\)表示点集\(i\)的导出子图中是否存在欧拉回路,\(f_i\)表示前若干个城市包含 ...
- [WC2018]州区划分——FWT+DP+FST
题目链接: [WC2018]州区划分 题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路.对于一种划分方案,第i个部分的 ...
- [WC2018]州区划分
[WC2018]州区划分 注意审题: 1.有序选择 2.若干个州 3.贡献是州满意度的乘积 枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0 存在欧拉回路:每个点都是偶度数,且图连通( ...
- [UOJ#348][WC2018]州区划分
[UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 ...
- [WC2018]州区划分(FWT,FST)
[WC2018]州区划分(FWT,FST) Luogu loj 题解时间 经典FST. 在此之前似乎用到FST的题并不多? 首先预处理一个子集是不是欧拉回路很简单,判断是否连通且度数均为偶数即可. 考 ...
- P4221 [WC2018]州区划分 无向图欧拉回路 FST FWT
LINK:州区划分 把题目中四个条件进行规约 容易想到不合法当前仅当当前状态是一个无向图欧拉回路. 充要条件有两个 联通 每个点度数为偶数. 预处理出所有状态. 然后设\(f_i\)表示组成情况为i的 ...
- [WC2018]州区划分(FWT)
题目描述 题解 这道题的思路感觉很妙. 题目中有一个很奇怪的不合法条件,貌似和后面做题没有什么关系,所以我们先得搞掉它. 也就是判断一个点集是否合法,也就是判断这个点集是否存在欧拉回路. 如果存在欧拉 ...
- Luogu4221 WC2018州区划分(状压dp+FWT)
合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方 ...
- 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 ...
- [WC2018]州区划分(状压DP+FWT/FMT)
很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...
随机推荐
- 项目经验记录丨Modbus转EtherNET/IP协议转换应用
使用电脑通过软件来进行模拟 EtherNET/IP主站连接Mdodbus从站设备的项目记录.使用软件为EIPScan 模拟主站,通过Modbus转EtherNET/IP网关连接Modbus Slave ...
- 万答#5,binlog解析出来的日志为何无法恢复
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 问题描述 问题来自一位群友,简单说就是用 mysqlbinlog 工具读取 bi ...
- JDK数组阻塞队列源码深入剖析
JDK数组阻塞队列源码深入剖析 前言 在前面一篇文章从零开始自己动手写阻塞队列当中我们仔细介绍了阻塞队列提供给我们的功能,以及他的实现原理,并且基于谈到的内容我们自己实现了一个低配版的数组阻塞队列.在 ...
- HttpClient 在vivo内销浏览器的高并发实践优化
作者:vivo 互联网服务器团队- Zhi Guangquan HttpClient作为Java程序员最常用的Http工具,其对Http连接的管理能简化开发,并且提升连接重用效率:在正常情况下,Htt ...
- java-servlet-转发AND路径
转发: a) 什么是转发?一个web组件将未完成的任务交给另一个web组件继续做.通常是一个servlet将数据获取之后转交给jsp进行展现.注:web组件值得是servlet或者jsp b) 如何转 ...
- HDFS的读写流程——宏观与微观
HDFS的读写流程--宏观与微观 HDFS:分布式文件系统,负责存放数据 分布式文件系统:就是将我们的数据放到多台电脑上存储. 写数据:就是将客户端上的数据上传到HDFS 宏观过程 客户端向HDFS发 ...
- java数组---数组的使用(打印,求和,最大值)
public static void main(String[] args) { int[] arrays={1,2,3,4,5}; //打印该数组 for (int i = 0; i < ar ...
- shellcode 注入执行技术学习
shellcode 注入执行技术学习 注入执行方式 CreateThread CreateRemoteThread QueueUserAPC CreateThread是一种用于执行Shellcode的 ...
- 不想当Window的Dialog不是一个好Modal,弹窗翻身记
弹窗是我们熟视无睹的一种交互方式,经常用到,但从没好好想过这种交互行为背后的意义... 弹窗是Windows的灵魂 Windows的灵魂是什么?当然是Window,当方便快捷的多窗口进入人们视野的时候 ...
- vue简单的请求api并渲染到表格
环境 vue3.11 组件库 https://element-plus.gitee.io/#/zh-CN 开始 初始化一个项目 App.vue <template> <div> ...