bzoj5153 [Wc2018]州区划分

题目链接

正解:子集和变换。

考场上只会暴力和$p=0$的情况,还只会$O(2^{n}*n^{3})$的。

然而这题题面出锅,导致考场上一直在卡裸暴力,后面的部分分没写了。。听$laofu$说$O(2^{n}*n^{3})$可以过。。

所以直接讲正解。。

我们假设每个城市可以在两个不同集合,那么可以把子集卷积变成或卷积。

我们只要记下当前总共有多少个点,于是考虑设$f[i][S]$表示$i$个点,集合为$S$的方案数。

最后的$f[n][all]$就是答案,显然这个状态中的每个城市只会出现一次。

那么$f[i][S]=\sum f[j][T]*(\frac{sum[A]}{sum[S]})^{p}$,其中$A|T=S$,且$A$是一个合法集合。

可以把分母移项到左边,然后我们可以设$g[i][S]$表示如果$S$是一个合法集合,且$S$的位数为$i$,那么$g[i][S]=sum[S]^{p}$,否则为$0$。

那么$f[i][S]*sum[S]^{p}=\sum f[j][T]*g[i-j][A]$。注意到这个式子可以直接$FMT$以后点乘,再$IFMT$回来以后作除法得到,总复杂度为$O(2^{n}*n^{2})$。

感觉这道题其实并没有那么难,但是考场上被题面以及固定的套路给局限住了,所以并没有想到可以交换$dp$的两维状态从而优化复杂度。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define rhl (998244353)
 6 #define N (1<<21|1)
 7
 8 using namespace std;
 9
10 int fa[25],g[25],w[N],cnt[N],can[N],inv[10005],n,m,p,all;
11 int f[22][N],h[22][N];
12
13 il int gi(){
14   RG int x=0,q=1; RG char ch=getchar();
15   while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar();
16   if (ch==‘-‘) q=-1,ch=getchar();
17   while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
18   return q*x;
19 }
20
21 il int qpow(RG int a,RG int b){
22   if (!b) return 1;
23   if (b==1) return a;
24   return 1LL*a*a%rhl;
25 }
26
27 il void fmt(int *a){
28   for (RG int i=1;i<all;i<<=1)
29     for (RG int j=0;j<all;++j){
30       if (j&i) a[j]+=a[j^i];
31       if (a[j]>=rhl) a[j]-=rhl;
32     }
33   return;
34 }
35
36 il void ifmt(int *a){
37   for (RG int i=1;i<all;i<<=1)
38     for (RG int j=0;j<all;++j){
39       if (j&i) a[j]-=a[j^i];
40       if (a[j]<0) a[j]+=rhl;
41     }
42   return;
43 }
44
45 il int find(RG int x){
46   return fa[x]==x ? x : fa[x]=find(fa[x]);
47 }
48
49 int main(){
50 #ifndef ONLINE_JUDGE
51   freopen("walk.in","r",stdin);
52   freopen("walk.out","w",stdout);
53 #endif
54   n=gi(),m=gi(),p=gi(),all=1<<n,inv[1]=1;
55   for (RG int i=1,u,v;i<=m;++i)
56     u=gi()-1,v=gi()-1,g[u]|=1<<v,g[v]|=1<<u;
57   for (RG int i=2;i<=3000;++i)
58     inv[i]=1LL*(rhl-rhl/i)*inv[rhl%i]%rhl;
59   for (RG int i=0;i<n;++i) w[1<<i]=gi(); fmt(w);
60   for (RG int i=1;i<all;++i) cnt[i]=cnt[i>>1]+(i&1);
61   for (RG int i=1,fg,lst;i<all;++i){
62     fg=0,lst=-1;
63     for (RG int j=0;j<n;++j) fa[j]=j;
64     for (RG int j=0;j<n;++j){
65       if (!(i>>j&1)) continue;
66       for (RG int k=0,x,y;k<n;++k){
67     if (!(i>>k&1) || !(g[j]>>k&1)) continue;
68     x=find(j),y=find(k); if (x!=y) fa[x]=y;
69       }
70     }
71     for (RG int j=0;j<n;++j){
72       if (i>>j&1){
73     if (lst==-1) lst=find(j);
74     else if (lst!=find(j)){ fg=1; break; }
75       }
76       if ((i>>j&1) && (cnt[g[j]&i]&1)){ fg=1; break; }
77     }
78     can[i]=fg;
79   }
80   for (RG int i=0;i<all;++i) if (can[i]) h[cnt[i]][i]=qpow(w[i],p);
81   for (RG int i=1;i<=n;++i) fmt(h[i]); f[0][0]=1,fmt(f[0]);
82   for (RG int i=1;i<=n;++i){
83     int *F=f[i];
84     for (RG int j=0;j<i;++j){
85       int *a=f[j],*b=h[i-j];
86       for (RG int s=0;s<all;++s)
87     F[s]=(1LL*a[s]*b[s]+F[s])%rhl;
88     }
89     ifmt(F);
90     for (RG int s=0;s<all;++s)
91       F[s]=i==cnt[s]?1LL*F[s]*qpow(inv[w[s]],p)%rhl:0;
92     if (i^n) fmt(F);
93   }
94   cout<<f[n][all-1]; return 0;
95 }

原文地址:https://www.cnblogs.com/wfj2048/p/8443080.html

时间: 2024-08-30 17:04:58

bzoj5153 [Wc2018]州区划分的相关文章

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

[UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 \(n\) 座城市划分成若干个州,每个州由至少一个城市组成,每个城市在恰好一个州内. 假设小 \(S\) 将这些城市划分成了 \(k\) 个州,设 \(V_i\) 是第 \(i\) 个州包含的所有城市组成的集合. 定义一条道路是一个州的内部道路,当且仅当这条道路的两个端点城市都在这个州内. 如果一

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

合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方案的满意度之和,枚举子集转移,则有f[S]=Σg[S']*f[S^S']*(sum[S']/sum[S])p (S'?S),其中g[S]为S集合是否合法,sum[S]为S集合人口数之和.复杂度O(3n).这个式子非常显然,就这么送了50分.p这么小显得非常奇怪但也没有任何卵用. 考虑优化.转移方程写

WC2018 州区划分

题目描述: luogu 题解: 设$f[S]$表示选集合$S$时所有满意度乘积之和,$W[S]$表示集合$S$中选中的$w$之和.显然有这样一个式子:$$f[S]= \frac{1}{W[S]^p} \sum\limits_{T \subseteq S}f[T]*W[S-T]^p*[check(S-T)]$$ 后面$check$的意思是判断$S-T$是否合法. 原题义中不合法的条件是存在一条欧拉回路.那么: 若图不连通则不存在. 若一个点的度数是奇数则不存在 单个点一定存在 这样可以$O(2^n

UOJ348. 【WC2018】州区划分

UOJ348. [WC2018]州区划分 http://uoj.ac/problem/348 分析: 设\(g(S)=(\sum\limits_{x\in S}w_x)^p[合法]\) \(f(S)\)表示\(S\)集合内的答案. \(f(S)=\sum\limits_{T\subseteq S,|T|>0}g(T)f(S-T)s(S)\). 这玩意可以使用占位多项式搞搞. 大概就是形如\(f(S)=\sum\limits_{P|Q=S,|P|+|Q|=S}g(P)h(Q)\). 多开一维表示\

UOJ#348. 【WC2018】州区划分

原文链接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]$$ 这东西是

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

UOJ#348 州区划分

解:有一个很显然的状压...... 就设f[s]表示选的点集为s的时候所有方案的权值和. 于是有f[s] = f[s \ t] * (sum[t] / sum[s])P. 这枚举子集是3n的. 然后发现这是子集卷积,参考资料. 于是就FWT搞一下...看代码 1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 30, M = 2100000, MO = 998244353; 5 6 struct Edge {

13- 整数划分插入乘号积最大(四)

/*                                            整数划分(四)时间限制:1000 ms  |  内存限制:65535 KB难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到了一个难题,让他百思不得其解,他非常郁闷..亲爱的你能帮帮他吗? 问题是我们经常见到的整数划分,给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积 输入    第

栅格重分类和条件函数均可以实现对流量统计数据进行定义划分

ArcGIS水分分析工具的流向分析是基于D8单流向算法,如果分析使用的DEM存在凹陷点,就会产生汇,导致径流断流从而影响了分析结果.在前面章节<ArcGIS水文分析实战教程(2)ArcGIS水文分析工具的基本原理>中又介绍过D8算法,而<ArcGIS水文分析实战教程(4)地形预处理>章节中笔者也较少过如何创建无凹陷点得DEM数据,在使用流向分析工具之前可以先行阅读. 首先流向分析要使用填洼过的数据,确保DEM数据没有凹陷点.如果数据准备妥当,直接使用水文分析工具箱中的[流向]工具进