[WC2018]州区划分——FWT+DP+FST
题目链接:
题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路。对于一种划分方案,第i个部分的权值为这一部分中所有点的权值和比上前i部分所有点的权值和的p次方,一种划分方案的权值为每部分的权值之积。要求求出所有划分方案的权值之和。
我们设f[S]为选中点的状态集合为S时的答案(其中S为二进制状态),设T为S集合最后一次划分出的集合且要保证集合T合法,那么可以得到转移方程(其中sum代表集合中点权和):
$f[S]=\sum\limits_{T\subseteq S}^{ }f[S-T]*(\frac{sum[T]}{sum[S]})^p$
这个子集DP直接枚举子集的时间复杂度是O(3^n),显然过不去,但我们发现这个DP相当于枚举两个集合i,j满足$i\cap j= \varnothing ,i\cup j=S$
这个如果只有子集并的条件可以用直接用FWT来优化,但还要求交集为空的条件就不能一维DP优化了。
我们假设一个点能被划分到多个部分中,那么DP状态就变成了二维:f[i][S]表示选取点集合为S,每部分包含的点数和为i的答案。
设g[i][S]表示集合为S,选取点数为i时sum[S]的p次方,如果S不合法或|S|!=i,那么g[i][S]就为0。(其中|S|表示S集合中的点数即二进制状态中1的个数)
那么转移方程就变成了:
$f[i][S]=\sum\limits_{j=1}^{i}\sum\limits_{T\subseteq S}^{ }\frac{f[j][S-T]*g[i-j][T]}{sum[S]^p}$
这样我们对f数组和g数组进行FWT转化成子集和表达式然后DP,每次乘上sum[S]^p的逆元即可,最后的答案为f[|U|][U],其中U为全集。时间复杂度为O(2^n*n^2)。
再来说一下如何判欧拉回路:
这个很简单只要一个图联通且每个点的度数都是偶数,那么这个图就是欧拉回路,对于每个二进制状态预处理判断即可,用bfs或dfs或并查集判断都可以。预处理时间复杂度同样是O(2^n*n^2)。
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int f[22][2100000];
int g[22][2100000];
int n,m,p;
const int mod=998244353;
int x[10000];
int y[10000];
int s[30];
int fa[30];
int v[22];
int w[2100000];
int cnt;
int mask;
int lg[2100000];
int inv[2100000];
inline int find(int x)
{
if(fa[x]==x)
{
return x;
}
return fa[x]=find(fa[x]);
}
inline void FWT(int *f,int opt)
{
for(int k=2;k<=(1<<n);k<<=1)
{
for(int i=0,t=k>>1;i<(1<<n);i+=k)
{
for(int j=i;j<i+t;j++)
{
if(opt==1)
{
f[j+t]=(f[j+t]+f[j])%mod;
}
else
{
f[j+t]=(f[j+t]-f[j]+mod)%mod;
}
}
}
}
}
inline int quick_pow(int x,int y)
{
int res=1;
while(y)
{
if(y&1)
{
res=1ll*res*x%mod;
}
y>>=1;
x=1ll*x*x%mod;
}
return res;
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
}
mask=(1<<n)-1;
for(int i=1;i<=n;i++)
{
lg[1<<(i-1)]=i;
}
for(int i=1;i<=mask;i++)
{
int sum=0;
for(int j=0;j<n;j++)
{
if(i&(1<<j))
{
w[i]+=v[j+1];
sum++;
}
}
int num=sum;
inv[i]=quick_pow(w[i],mod-2);
for(int j=1;j<=n;j++)
{
fa[j]=j;
s[j]=0;
}
for(int j=1;j<=m;j++)
{
if(((1<<(x[j]-1))&i)&&((1<<(y[j]-1))&i))
{
int u=find(x[j]);
int v=find(y[j]);
if(u!=v)
{
sum--;
fa[u]=v;
}
s[x[j]]++;
s[y[j]]++;
}
}
int flag=0;
for(int j=0;j<n;j++)
{
if((1<<j)&i)
{
flag|=(s[j+1]&1);
}
}
if(flag||sum>1)
{
g[num][i]=quick_pow(w[i],p);
}
}
f[0][0]=1;
FWT(f[0],1);
for(int i=0;i<=n;i++)
{
FWT(g[i],1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
for(int k=0;k<=mask;k++)
{
f[i][k]+=1ll*g[j][k]*f[i-j][k]%mod;
f[i][k]%=mod;
}
}
FWT(f[i],-1);
for(int k=0;k<=mask;k++)
{
f[i][k]=1ll*f[i][k]*quick_pow(inv[k],p)%mod;
}
if(i<n)
{
FWT(f[i],1);
}
}
printf("%d",f[n][mask]);
}
[WC2018]州区划分——FWT+DP+FST的更多相关文章
- P4221 [WC2018]州区划分 无向图欧拉回路 FST FWT
LINK:州区划分 把题目中四个条件进行规约 容易想到不合法当前仅当当前状态是一个无向图欧拉回路. 充要条件有两个 联通 每个点度数为偶数. 预处理出所有状态. 然后设\(f_i\)表示组成情况为i的 ...
- [WC2018]州区划分(FWT)
题目描述 题解 这道题的思路感觉很妙. 题目中有一个很奇怪的不合法条件,貌似和后面做题没有什么关系,所以我们先得搞掉它. 也就是判断一个点集是否合法,也就是判断这个点集是否存在欧拉回路. 如果存在欧拉 ...
- [WC2018]州区划分(FWT,FST)
[WC2018]州区划分(FWT,FST) Luogu loj 题解时间 经典FST. 在此之前似乎用到FST的题并不多? 首先预处理一个子集是不是欧拉回路很简单,判断是否连通且度数均为偶数即可. 考 ...
- [UOJ#348][WC2018]州区划分
[UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 ...
- [WC2018]州区划分
[WC2018]州区划分 注意审题: 1.有序选择 2.若干个州 3.贡献是州满意度的乘积 枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0 存在欧拉回路:每个点都是偶度数,且图连通( ...
- [WC2018]州区划分(状压,子集卷积)
[洛谷题面]https://www.luogu.org/problemnew/show/P4221 首先考虑判定一个子图是否合法: (1)连通:并查集判断即可. (2)没有欧拉回路:存在欧拉回路的条件 ...
- Luogu4221 WC2018州区划分(状压dp+FWT)
合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方 ...
- [WC2018]州区划分(状压DP+FWT/FMT)
很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...
- uoj#348/洛谷P4221 [WC2018]州区划分(FWT)
传送门(uoj) 传送门(洛谷) 全世界都会子集卷积就咱不会--全世界都在写\(FMT\)就咱只会\(FWT\)-- 前置芝士 或运算\(FWT\)或者\(FMT\) 左转洛谷模板区,包教包会 子集卷 ...
随机推荐
- iOS开发简记(7):网络请求模块
主流的APP都少不了跟服务器交互,网络请求是少不了的事情. 开源的网络请求库,有很多,比如:AFNetworking.YTKNetwork.PPNetworkHelper.ASIHttpRequest ...
- 豆瓣读书爬虫(requests + re)
前面整理了一些爬虫的内容,今天写一个小小的栗子,内容不深,大佬请忽略.内容包括对豆瓣读书网站中的书籍的基本信息进行爬取,并整理,便于我们快速了解每本书的中心. 一.爬取信息 每当爬取某个网页的信息时, ...
- RNG牛掰!
2018-05-21 RNG牛掰!Uzi圆梦! 不说了,先去哭了! 2018-07-08 洲际赛后更新,RNG依然牛逼! 2018-08-30 亚运后后更新,UZI加油! 2018-10-22 继续加 ...
- 每秒高达1.6亿次操作的并发键值存储库 FASTER 诞生
FASTER 在过去十年中,云中的数据密集型应用程序和服务有了巨大的增长.数据在各种边设施(例如,设备,浏览器和服务器)上创建,并由云应用程序处理用来获得数据价值或做出决策.应用程序和服务可以处理收集 ...
- C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 访问记录功能改进
当用户数据非常庞大时需要一个功能,就是统计各种账户的访问系统的情况,用户数量的各种参数需要让管理者心里有个数. 1:信息系统中有多少有效账户?可以很方便能知道具体个数,让管理者心里有个数. 2:某个公 ...
- 剑指Offer-- 二叉搜索树的第K个结点
给定一颗二叉搜索树,请找出其中的第k大的结点.例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4. /* struct TreeNode { int va ...
- Effective java 43返回零长度的数组或者集合而不是null
- java.lang.LinkageError: JAXB 2.0 API is being loaded from the bootstrap classloader
我的解决办法: 1.如果是application工程,则在程序中打印出 system.out.println(System.getProperty("java.endo ...
- C#设计模式之10:状态模式
状态模式 状态模式将合适的Context(上下文)模拟成一个状态机,在这个状态机的内部,由Context来决定整个状态机的状态,再根据不同的状态执行不同的方法.在C#编译器的帮助下,很多语法糖的背后都 ...
- 一次linux问题分析原因的简要记录
1. 这边功能测试 一个linux服务器 4c 16g的内存 发现总是出现异常. dotnet run 起来的一个 程序 总是会被killed 现象为: 2. 一开始怀疑是 打开的文件描述符过多 引起 ...