[WC2018]州区划分(FWT)
题解
这道题的思路感觉很妙。
题目中有一个很奇怪的不合法条件,貌似和后面做题没有什么关系,所以我们先得搞掉它。
也就是判断一个点集是否合法,也就是判断这个点集是否存在欧拉回路。
如果存在欧拉回路每个点的度都得是偶数而且图联通,这个条件扫描一遍在上一个并查集就可以判掉了。
然后开始统计答案。
n很小,可以考虑状压dp,我们设dp[s]为已经划分好的州区点集和为s它的所有方案的答案的和。
转移可以考虑枚举子集。
dp[s]=∑dp[s']*(sum[s^s']/sum[s])p
然后我们发现sum[s]p是和转移的枚举无关的,所以我们可以稍稍变换一下变成
dp[s]*sum[s]p=∑dp[s']*sum[s^s']p
这样的复杂度是3n的,我们要考虑优化。
我们换一种枚举方式
dp[S]*sum[s]p=∑dp[s]*sum[s']p (s&s'==0)&&(s|s'==S)
如果没有前面那个条件,那么它就是一个形式有点奇怪的或卷积,在加上那个烦人的条件,就有点让人怀疑人生了。。
然后关键的思路来了,考虑到这道题时限较长,复杂度可以在卷积的基础上加一个n,所以我们把dp状态多开一维。
我们设dp[i][S]表示在S点集中有i个点的答案。
这样的状态设计虽然带来了大量冗余状态,却方便了我们的转移。
dp[i][S]=∑dp[j][s]*sum[i-j][s']p (s|s'==S)
这样我们成功的用一个n的时间复杂度把这个东西变成了一个正常的或卷积,直接上FWT就可以了。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 22
#define R register
using namespace std;
typedef long long ll;
int n,m,p,lowb[<<],cou[<<],size,du[N],fa[N];
ll f[N][<<],g[N][<<],w[N],sum[<<],ny[<<];
bool a[N][N],b[N];
const int mod=;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline ll power(ll x,ll y){
ll ans=;
while(y){if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;}
return ans;
}
inline ll ni(ll x){return power(x,mod-);}
inline void MOD(ll &x){x=(x+mod)%mod;}
inline void FWT(ll *a,int tag){
for(R int i=;i<size;i<<=)
for(R int j=;j<size;j+=(i<<))
for(R int k=;k<i;++k)MOD(a[i+j+k]+=tag*a[j+k]);
}
int find(int x){return fa[x]=fa[x]==x?x:find(fa[x]);}
int main(){
n=rd();m=rd();p=rd();int u,v;size=(<<n);
for(R int i=;i<=m;++i){u=rd();v=rd();a[u][v]=a[v][u]=;}
for(R int i=;i<=n;++i)w[i]=rd();
for(R int i=;i<size;i<<=)lowb[i]=lowb[i>>]+;
for(R int s=;s<size;++s){
cou[s]=cou[s>>]+(s&);bool haha=;int num=cou[s];
for(R int i=;i<=n;++i){if(s&(<<i-))sum[s]+=w[i],b[i]=;else b[i]=;du[i]=;fa[i]=i;}
for(R int i=;i<=n;++i)if(b[i])for(int j=i+;j<=n;++j)if(a[i][j]&&b[j]){
du[i]++,du[j]++;
int xx=find(i),yy=find(j);if(xx!=yy)fa[xx]=yy,num-=;
}
for(R int i=;i<=n;++i)if(du[i]&){haha=;break;}
if(num!=)haha=;
if(!haha)continue;
g[cou[s]][s]=power(sum[s],p);
}
for(R int s=;s<size;++s)ny[s]=ni(power(sum[s],p));
for(R int i=;i<=n;++i)FWT(g[i],);
f[][]=;FWT(f[],);
for(R int i=;i<=n;++i){
for(R int j=;j<i;++j){
for(R int k=;k<size;++k)(f[i][k]+=f[j][k]*g[i-j][k])%=mod;
}
FWT(f[i],-);
for(R int j=;j<size;++j)f[i][j]=f[i][j]*ny[j]%mod;
if(i<n)FWT(f[i],);
}
printf("%lld",f[n][size-]);
return ;
}
[WC2018]州区划分(FWT)的更多相关文章
- [WC2018]州区划分——FWT+DP+FST
题目链接: [WC2018]州区划分 题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路.对于一种划分方案,第i个部分的 ...
- [WC2018]州区划分(FWT,FST)
[WC2018]州区划分(FWT,FST) Luogu loj 题解时间 经典FST. 在此之前似乎用到FST的题并不多? 首先预处理一个子集是不是欧拉回路很简单,判断是否连通且度数均为偶数即可. 考 ...
- [WC2018]州区划分
[WC2018]州区划分 注意审题: 1.有序选择 2.若干个州 3.贡献是州满意度的乘积 枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0 存在欧拉回路:每个点都是偶度数,且图连通( ...
- [UOJ#348][WC2018]州区划分
[UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 ...
- P4221 [WC2018]州区划分 无向图欧拉回路 FST FWT
LINK:州区划分 把题目中四个条件进行规约 容易想到不合法当前仅当当前状态是一个无向图欧拉回路. 充要条件有两个 联通 每个点度数为偶数. 预处理出所有状态. 然后设\(f_i\)表示组成情况为i的 ...
- Luogu4221 WC2018州区划分(状压dp+FWT)
合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方 ...
- [WC2018]州区划分(状压DP+FWT/FMT)
很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...
- uoj#348/洛谷P4221 [WC2018]州区划分(FWT)
传送门(uoj) 传送门(洛谷) 全世界都会子集卷积就咱不会--全世界都在写\(FMT\)就咱只会\(FWT\)-- 前置芝士 或运算\(FWT\)或者\(FMT\) 左转洛谷模板区,包教包会 子集卷 ...
- [LOJ#2340] [WC2018] 州区划分
题目链接 洛谷题面. LOJ题面.还是LOJ机子比较快 Solution 设\(f(s)\)表示选\(s\)这些城市的总代价,那么我们可以得到一个比较显然的\(dp\): \[ f(s)=\frac{ ...
随机推荐
- Ubuntu Linux Recovery Mode
在安全模式/修復模式有以下的選項︰resume Resume normal boot繼續正常啟動作業,供不小心誤入此選單的使用者開機使用.(继续以正常模式启动) clean Try to make f ...
- 基于CRM跟进(活动)记录中关键字识别的客户跟进加权值的成单概率算法
1.提取销售人员的跟进记录,分析其中的骂人文字(负面情绪),将有负面情绪的客户的跟进排期,进行降权(权重)操作.重点跟进加权值较高的客户. 执行办法: 将销售与客户沟通的语音:电话,微信,QQ,通过调 ...
- 认识Debian
Debian -- 通用操作系统https://www.debian.org/ DebianStretch - Debian Wikihttps://wiki.debian.org/DebianStr ...
- Docker -d : Running modprobe bridge nf_nat failed with message: exit status 1
nf_nat 是做什么用的 - DockOne.iohttp://dockone.io/question/1384 docker-py的配置与使用 - openxxs - 博客园http://www. ...
- C# List用法 List介绍
一.#List泛型集合 集合是OOP中的一个重要概念,C#中对集合的全面支持更是该语言的精华之一. 为什么要用泛型集合? 在C# 2.0之前,主要可以通过两种方式实现集合: a.使用ArrayList ...
- [转帖]你所不知道的C和C++运行库
[C-C++]你所不知道的C和C++运行库 https://blog.csdn.net/humanking7/article/details/85887884 原作者也是转的blog 最近一个物理机上 ...
- 通过view实现rest api接口
Django rest framwork之view 基于Django的View实现Json数据的返回: # _*_ encoding:utf-8 _*_ __author__ = 'LYQ' __da ...
- rsync: chgrp "/.hosts.NBCxBB" (in test) failed: Operation not permitted (1)
#记一次rsync出现的错误(网上基本都是说权限问题) #这并不是权限的问题,应为实际的文件已经传过去了,但是rsync就是会报这个错误,(虽然使用是正常的,但是看着就是不爽) [root@local ...
- nfs+keepalived高可用
1台nfs主被服务器都下载nfs.keepalived yum install nfs-utils rpcbind keepalived -y 2台nfs服务器nfs挂载目录及配置必须相同 3.在主n ...
- PLSQL 错误问题:Datebase character set (AL32UTF-8) and Client character set (ZHS16GBK) are different.
(解决不了,网上用的是Orecal,我用的只是客户端.) 网上找到解决方法 打开注册表(ctr+R,输入regedit),根据报错提示找到注册表位置,但本机是win10 64位系统,根据以上路径找不到 ...