题目链接

洛谷题面

LOJ题面。还是LOJ机子比较快

Solution

设\(f(s)\)表示选\(s\)这些城市的总代价,那么我们可以得到一个比较显然的\(dp\):

\[f(s)=\frac{1}{sum_s^p}\sum_{t\subset s} f(t)g(s-t)
\]

其中\(g(i)\)表示合法的\(sum_i^p\),即若不合法则为\(0\)。

这个\(dp\)是\(O(3^n)\)的,注意到这是个子集卷积的形式,我们可以考虑用\(fwt\)优化它。

那么我们可以一层一层的\(dp\),即按照\(bitcnt(s)\)的顺序从小到大计算\(f\),假设当前算到了\(bitcnt=i\),那么那些\(bitcnt<i\)的\(f\)肯定已经算完了,所以我们可以用\(fwt\)加速来算好当前层的\(f\)。

容易发现这样做的复杂度是\(O(n^22^n)\)的,足以通过此题。

洛谷机子好慢啊...要开O2才能过,loj一半时限就过了

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double
#define ll long long const int maxn = (1<<21)+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 998244353; int cnt[maxn],sum[maxn],g[22][maxn];
int f[22][maxn],n,m,p,w[30],fa[30],d[30],head[30],tot,inv[maxn];
struct edge{int to,nxt;}e[900]; void Add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
void ins(int u,int v) {Add(u,v),Add(v,u);} int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);} int add(int x,int y) {return x+y>mod?x+y-mod:x+y;}
int del(int x,int y) {return x-y<0?x-y+mod:x-y;}
int mul(int x,int y) {return 1ll*x*y-1ll*x*y/mod*mod;} int check(int s) {
if(cnt[s]==1) return 0;
for(int i=1;i<=n;i++) fa[i]=i,d[i]=0;
for(int x=1;x<=n;x++)
if(s>>(x-1)&1) {
for(int u,v,i=head[x];i;i=e[i].nxt) {
if(!(s>>(e[i].to-1)&1)) continue;
d[e[i].to]++;
if((u=find(x))!=(v=find(e[i].to))) fa[u]=v;
}
}
int rt=__builtin_ctz(s&-s)+1;
for(int i=1;i<=n;i++) if(s>>(i-1)&1) if(find(i)!=find(rt)||(d[i]&1)) return 1;
return 0;
} void fwt(int *r,int N) {
for(int i=1;i<N;i<<=1)
for(int j=0;j<N;j+=i<<1)
for(int k=0;k<i;k++)
r[i+j+k]=add(r[i+j+k],r[j+k]);
} void ifwt(int *r,int N) {
for(int i=1;i<N;i<<=1)
for(int j=0;j<N;j+=i<<1)
for(int k=0;k<i;k++)
r[i+j+k]=del(r[i+j+k],r[j+k]);
} int qpow(int a,int x) {
int res=1;
for(;x;x>>=1,a=mul(a,a)) if(x&1) res=mul(res,a);
return res;
} int main() {
read(n),read(m),read(p);
for(int i=1,x,y;i<=m;i++) read(x),read(y),ins(x,y);
for(int i=1;i<=n;i++) read(w[i]);
int all=1<<n;
for(int i=1;i<all;i++) cnt[i]=__builtin_popcount(i);
for(int i=1;i<all;i++) sum[i]=w[__builtin_ctz(i&-i)+1]+sum[i^(i&-i)];
for(int i=1;i<all;i++) sum[i]=qpow(sum[i],p);
for(int i=0;i<all;i++) g[cnt[i]][i]=sum[i]*check(i),inv[i]=qpow(sum[i],mod-2);
for(int i=0;i<=n;i++) fwt(g[i],all);
f[0][0]=1;fwt(f[0],all);
for(int i=1;i<=n;i++) {
for(int j=0;j<i;j++)
for(int s=0;s<all;s++)
f[i][s]=add(f[i][s],mul(f[j][s],g[i-j][s]));
ifwt(f[i],all);
for(int s=0;s<all;s++) f[i][s]=cnt[s]==i?mul(f[i][s],inv[s]):0;
if(i!=n) fwt(f[i],all);
}
write(f[n][all-1]);
return 0;
}

[LOJ#2340] [WC2018] 州区划分的更多相关文章

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

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

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

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

  3. [WC2018]州区划分

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. excell 导入 导出

    1.jar包 2.POIUtils工具类 package com.esstglobal.service.utils; import java.io.BufferedInputStream; impor ...

  2. 【springboot-01】整合quartz

    1.什么是quartz? quartz是一个开源的定时任务框架,具备将定时任务持久化至数据库以及分布式环境下多节点调度的能力.当当的elastic-job便是以quartz为基础,结合zookeepe ...

  3. 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)

    题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...

  4. 「题目代码」P1039~P1043(Java)

    P1039 谭浩强C语言(第三版)习题4.9 import java.util.*; import java.io.*; import java.math.BigInteger; public cla ...

  5. 微信小程序—day04

    元素水平+垂直居中 昨天的用户页的用户头像,是根据已知的像素大小,设置固定的值,达到居中的效果. 今日切换机型进行适配,发现对不同尺寸大小的屏幕不匹配.所以对wxss进行修改,真正达到水平+垂直居中. ...

  6. 【循环控制器】-(针对中间部分要循环的场景,相当于loadrunner的action部分)

    一般使用 setup线程组 + teardown组 针对中间要循环的部分   使用循环处理器    单独循环中间的部分,相当于loadrunner的action部分

  7. 56[LeetCode] .Merge Intervals

    Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums s ...

  8. 5.hadoop常用命令

    1. 单独启动和关闭hadoop服务 启动名称节点 #hadoop-daemon.sh start namenode 启动数据节点 #hadoop-daemons.sh start datanode ...

  9. HDU 4300 Clairewd’s message (next函数的应用)

    题意:给你一个明文对密文的字母表,在给你一段截获信息,截获信息前半段是密文,后半段是明文,但不清楚它们的分界点在哪里,密文一定是完整的,明文可能是残缺的,求完整的信息串(即完整的密文+明文串). 题解 ...

  10. Python中的Numeric

    整型Integer 在Python2.X中,Integer有两种类型,一种是32bit的普通类型,一种是精度无限制的long类型,在数字后面标识l或者L来标识long类型,并且,当32bit发生ove ...