原文链接www.cnblogs.com/zhouzhendong/p/UOJ348.html

前言

第一次知道子集卷积可以自己卷自己。

题解

这是一道子集卷积模板题。

设 $sum[S]$ 表示点集 S 的点权和。

设 $f[S]$ 表示对点集 S 进行州区划分得到的答案,定义 $g[S]$ 在点集 S 合法时为 $(sum[S])^p$,不合法时为 0 。

$$f[S] = \frac{1}{(sum[S])^p}\sum_{T\subsetneq S} f[T]g[S-T]$$

这东西是个子集卷积的形式。

但是在卷的时候要调用自己。

那怎么办?

一边做子集卷积,一边得出新答案。

具体地:枚举一下集合大小 S ,每次通过之前的结果做卷积求出当前集合大小的所有集合的答案。

直接保留 FMT 后的结果,方便计算、降低时间复杂度。

具体细节见代码。

时间复杂度 $O(n^22^n)$ 。

代码

#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> vi;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=23,S=1<<21,mod=998244353;
const ULL Bmod=16ULL*mod*mod;
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=(LL)x*x%mod)
if (y&1)
ans=(LL)ans*x%mod;
return ans;
}
void Add(int &x,int y){
if ((x+=y)>=mod)
x-=mod;
}
void Del(int &x,int y){
if ((x-=y)<0)
x+=mod;
}
int n,m,s,p;
vector <int> e[N];
int w[N];
int cnt1[S],sum[S],f[S];
int g[N][N];
int u[N][S],v[N][S];
int check(int s){
static int vis[N],in[N],q[N],head,tail,x;
if (!s)
return 0;
clr(vis),clr(in);
int fir=-1;
For(i,0,n-1)
if (s>>i&1){
fir=i;
break;
}
head=tail=0;
q[++tail]=fir,vis[fir]=1;
while (head<tail){
x=q[++head];
for (auto y : e[x])
if (s>>y&1){
in[y]^=1;
if (!vis[y])
vis[y]=1,q[++tail]=y;
}
}
if (tail!=cnt1[s])
return 1;
For(i,0,n-1)
if (in[i])
return 1;
return 0;
}
void FMT(int *a){
For(i,0,n-1)
For(j,0,s-1)
if (j>>i&1)
Add(a[j],a[j^1<<i]);
}
void IFMT(int *a){
For(i,0,n-1)
For(j,0,s-1)
if (j>>i&1)
Del(a[j],a[j^1<<i]);
}
int main(){
n=read(),m=read(),p=read();
s=1<<n;
clr(g);
For(i,1,m){
int x=read()-1,y=read()-1;
e[x].pb(y),e[y].pb(x);
}
For(i,0,n-1)
w[i]=read();
For(i,0,s-1){
For(j,0,n-1)
if (i>>j&1){
cnt1[i]++;
sum[i]+=w[j];
}
f[i]=check(i);
sum[i]=Pow(sum[i],p);
if (f[i])
u[cnt1[i]][i]=sum[i];
}
For(i,0,n)
FMT(u[i]);
v[0][0]=1;
FMT(v[0]);
For(i,1,n){
For(k,0,s-1){
ULL tmp=0;
For(j,0,i-1){
tmp+=(LL)v[j][k]*u[i-j][k];
if (tmp>=Bmod)
tmp-=Bmod;
}
v[i][k]=tmp%mod;
}
IFMT(v[i]);
For(k,0,s-1)
if (cnt1[k]==i)
v[i][k]=(LL)v[i][k]*Pow(sum[k],mod-2)%mod;
else
v[i][k]=0;
FMT(v[i]);
}
IFMT(v[n]);
cout<<v[n][s-1]<<endl;
return 0;
}

  

UOJ#348. 【WC2018】州区划分的更多相关文章

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

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

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

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

  3. [WC2018]州区划分

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

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

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

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

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

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

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

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

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

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

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

  9. 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 ...

  10. [WC2018]州区划分(状压DP+FWT/FMT)

    很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...

随机推荐

  1. Linux,Ubuntu,Mint 环境下 navicat 乱码问题

    1. 官方下载好以后,进入目录 执行 ./start_navicat  可以启动软件. 2. 如果有乱码,首先,使用编辑器打开 start_navicat ,比如 vim start_navicat ...

  2. sql0001

    001.   https://blog.csdn.net/qinshi965273101/article/details/81907658 002.    https://blog.csdn.net/ ...

  3. Hper-V卸载

    1.txt文件输入以下内容,后缀改为cmd,以管理员身份执行 mountvol X: /s copy %WINDIR%\System32\SecConfig.efi X:\EFI\Microsoft\ ...

  4. 【题解】魔板—洛谷P1275。

    话说好久没更博了. 最近学了好多知识懒的加进来了. 有幸认识一位大佬. 让我有了继续更博的兴趣. 但这是一个旧的题解. 我在某谷上早就发过的. 拿过来直接用就当回归了吧. 其实这道题有一个特别关键的思 ...

  5. SQL server 数据库中插入中文变???格式乱码的问题另一种容易忽略的情况(C#操作dapper)

    1.先查查 VS2015 中的XXX.cs页面中编码格式,记事本打开另存一下,编码格式可能是ANSI改为unioncode. (中文前面加N或者改排序规则解决不了的情况有可能是以上原因.)

  6. osg做的路面项目

  7. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  8. Spring Cloud微服务集成配置中心

    1. 搭建Spring Cloud Config配置中心(见上一篇博客) 2. 创建微服务项目bounter-simon-app,pom文件如下: <?xml version="1.0 ...

  9. python使用正则解析网络地址的各个部分

    参考文章: https://www.cnblogs.com/ingd/p/6182571.htmlimport re def resolveAddress(url): ""&quo ...

  10. cookie记录横向滚动条位置

    一.Css <style type="text/css"> #x{ width: 100%; white-space: nowrap; overflow-x: scro ...