[WC2018]州区划分

2024-03-16 23:32
文章标签 划分 州区 wc2018

本文主要是介绍[WC2018]州区划分,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

州区划分

题解

挺水的题呀。

要求的是\sum ( \prod_{i=1}^{k} \frac{ \sum_{x \in V_{i}}w_{x}}{ \sum_{j=1}^{i} \sum_{x\in V_{j}}w_{x}})^p \, mod \, 998244353,需要保证V_{i}中不存在欧拉回路。

对于判欧拉回路,可以通过状压,求出S以内所有图的状态的是否为欧拉回路。

很容易想到dp,设f_{s}为集合s的答案,g_{s}表示集合s是否合法。于是乎,可以得到:

f_{s}= \sum_{t\in s}f_{s-t}g_{t}\left(\frac{val_{t}}{val_{s}} \right )^pval_{s}是集合s的的人口数,也就是所有包含的w的和。

枚举子集明显是O\left(3^n \right ),由于n\leq 21,明显会T。

于是我们可以将其卷积,变成了

f_{s}= \sum_{a\cap b= \o ,a\cup b= s}f_{a}g_{b}\left(\frac{val_{b}}{val_{s}} \right )^p,很明显的一个卷积,可以将后面那一块加入g_{b}中。

基于FMT的基本形式,可以将a \cup b =s变为\left | a \right |+ \left | b \right | = \left | s \right |

我们的式子变为f_{i,s}g_{i,s}= \sum_{j=0}^{i-1}\sum_{t\in s}f_{j,s-t}g_{i-j,t},通过FMT可以求出任意的f_{i,s}g_{i,s},再将g_{i,s}除掉就可以得到f_{i,s}了。

答案就是f_{n,S}

源码

代码太慢了,就加了一个超级优化。笔者又不是妹儿,加优化当然就不会T了

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN (1<<21)+5
#define reg register
typedef long long LL;
const int mo=998244353;
template<typename _T>
inline void read(_T &x){_T f=1;x=0;char s=getchar();while('0'>s||'9'<s){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
int n,m,p,pos[MAXN],e[22],w[MAXN],iw[MAXN],cnt[MAXN];
int f[22][MAXN],g[22][MAXN],nxt[MAXN];LL ans[MAXN];
inline int add(const int x,const int y){return x+y<mo?x+y:x+y-mo;}
inline int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;}
inline int inv(const int x){return x^1?mo-1ll*(mo/x)*inv(mo%x)%mo:1;}
inline void FWT(int *A,const int typ){for(reg int i=0;i<n;++i)for(reg int j=1;j<(1<<n);++j)if(j&(1<<i))A[j]=add(A[j],typ>0?A[j^(1<<i)]:mo-A[j^(1<<i)]);
}
signed main(){read(n);read(m);read(p);const int lim=(1<<n);for(reg int i=1;i<=n;++i)pos[1<<i-1]=i;for(reg int i=1;i<=m;++i){int u,v;read(u);read(v);e[u]|=(1<<v-1);e[v]|=(1<<u-1);}for(reg int i=0;i<n;++i)read(w[1<<i]);for(reg int i=1;i<lim;++i)nxt[i]=i&-i,cnt[i]=cnt[i^nxt[i]]+1;for(reg int j=1;j<lim;++j){w[j]=w[nxt[j]]+w[j^nxt[j]];int t=nxt[j];iw[j]=inv(qkpow(w[j],p));bool fg=0;for(reg int i=j;i;i^=nxt[i])if(cnt[e[pos[nxt[i]]]&j]&1){fg=1;break;}if(!fg)for(reg int i=nxt[j],k;i;)k=pos[nxt[i]],i^=nxt[i],i|=e[k]&j&~t,t|=e[k]&j;if(j==t&&!fg)continue;g[cnt[j]][j]=qkpow(w[j],p);}f[0][0]=1;FWT(f[0],1);int *a,*b;for(reg int i=1;i<=n;++i){FWT(g[i],1);for(int j=0;j<lim;j++)ans[j]=0;for(reg int j=0;j<i;++j){a=f[j];b=g[i-j];for(reg int k=0;k<lim;++k)ans[k]+=1ll*a[k]*b[k];}a=f[i];for(reg int j=0;j<lim;++j)a[j]=ans[j]%mo;FWT(a,-1);for(reg int j=0;j<lim;++j)a[j]=1ll*a[j]*iw[j]%mo;if(i<n)FWT(a,1);}printf("%d",f[n][lim-1]);return 0;
}

谢谢!!!

这篇关于[WC2018]州区划分的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/817092

相关文章

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

Thread如何划分为Warp?

1 .Thread如何划分为Warp? https://jielahou.com/code/cuda/thread-to-warp.html  Thread Index和Thread ID之间有什么关系呢?(线程架构参考这里:CUDA C++ Programming Guide (nvidia.com)open in new window) 1维的Thread Index,其Thread

【电子通识】洁净度等级划分及等级标准

洁净度常用于评估半导体、生物制药、医疗、实验室及科研院所、新能源等领域的洁净室、无尘室或者无菌室等环境。         一般来说,晶圆光刻、制造、测试等级为100级或1000级的洁净间,百级洁净间要求空气中0.5微米的尘埃粒子数不得超过每立方米3520个;等级为1000级的洁净间要求0.5微米的尘埃粒子数不得超过每立方米35200个。         晶圆切割或封装工序一

洛谷 凸多边形划分

T282062 凸多边形的划分 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 先整一个半成品,高精度过两天复习一下补上 #include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#include <vector>#include <map>

n条直线最多能划分出多少个平面?

N条直线,两两相交,其交点各不不同,则产生的交点数目为N个数中取2个数的组合; 同时,也只有这种情况下(两两相交,也交点不同),分割的平面数最多, 数目为: 2 + (N-1)(N+2)/2.  这里求最少平面数没有意义,因为最少平面数就是N+1, 即N条直线两两平行的时候,分割的平面最少。 举例: 1条直线分割平面数最多为2; a1 = 2 2条直线分割平面数最多为4;

在不损坏数据的情况下给WIN7重新划分分区

小易接到个求助电话:我的机器上已经装好了系统,但是只有一个分区。我不想重装系统重新分区,能不能再分出一个分区?   这个故障可能是困惑很多网友的一个故障。一般,有一些第三方的软件可以实现这些功能。但是,现在在 Windows Vista/Windows 7 里允许你对现有分区大小进行一定范围的调整。   来看一下操作办法:   准备工作   这个操作必须要求你的文件系统是 N

【非零段划分 / 2】

题目 思路 第一种思路:按照表面题意,枚举p,处理数组后进行计数: 复杂度 ∈ O ( n ⋅ m ) 复杂度 \in O(n \cdot m) 复杂度∈O(n⋅m) 第二种思路:把数组看成一个二维的山形图,先将相邻的水平线段转化成点(对数组unique),再对每个子结构进行考虑 复杂度 ∈ O ( m i n ( n , m ) ) 复杂度 \in O(\;min(

【JVM】JVM简介|运行流程|内存划分

目录 一、JVM简介 二、JVM运行流程 三、JVM运⾏时数据区(内存划分)  3.1 堆(线程共享) 3.2 栈 3.3 元数据区(方法区)(线程共享) 3.4 程序计数器(线程私有) 一、JVM简介 JVM是Java Virtua Machine的简称,意为Java虚拟机 虚拟机是指通过软件模拟的具有完整硬件功能的、运⾏在⼀个完全隔离的环境中的完整计算机系统 常⻅的虚

环上k划分的和的gcd的最大值【gcd基本性质的利用】

今早看到的题,想了下会做了,但是觉得这题挺有意思的,于是打算写一下做法。本题利用了gcd的基本性质:更相减损法以及结合律,平时做gcd的题基本没用到过这两性质,而本题对这性质进行了充分利用。 思路: 首先我们考虑给一个序列,我们该怎么做。 令 fn=∑ni=1ai f_n=\sum_{i=1}^n a_i。 我们考虑序列的一个 k+1 k+1划分 fx1,fx2−fx1,fx3−fx2