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]\ f(i-j,s1)*can(s2) *vals(s2)^p\)
记\(g(|s|,s)\)表示\(can(s)*vals(s)^p\),先在最开始DWT所有的g,枚举i,j,然后卷一下\(f_{i-j}\)与\(g_j\),只要在dp的过程中一直保持f是已经DWT了的,卷积的复杂度就只有\(O(2^n)\),记得\(f_i\)算完以后要IDWT一下乘上\(vals(s)^{-p}\)再DWT。复杂度\(O(n^22^n)\)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#define P puts("lala")
#define cp cerr<<"lala"<<endl
#define ln putchar('\n')
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
inline int read()
{
char ch=getchar();int g=1,re=0;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
return re*g;
}
typedef long long ll;
typedef pair<int,int> pii;
const int N=25;
const int mod=998244353;
inline ll qpow(ll a,int n)
{
ll ans=1;
for(;n;n>>=1,a=a*a%mod) if(n&1) ans=ans*a%mod;
return ans;
}
void FWT(int *a,int n,ll f)
{
for(int step=1;step<n;step<<=1)
for(int j=0;j<n;j+=(step<<1))
for(int k=j;k<j+step;++k)
{
int x=a[k],y=a[k+step];
a[k+step]=(y+f*x+mod)%mod;
}
}
int head[N],cnt=0;
struct node
{
int to,next;
}e[N*N];
inline void add(int x,int y)
{
e[++cnt]=(node){y,head[x]}; head[x]=cnt;
e[++cnt]=(node){x,head[y]}; head[y]=cnt;
}
int val[N],n,m,vals[1<<21|1],deg[N],fa[N];
bool can[1<<21|1];
pii edg[N*N];
inline int find(int x)
{
if(fa[x]!=x) return fa[x]=find(fa[x]);
return fa[x];
}
int f[23][1<<21|1],g[23][1<<21|1];
void wj()
{
#ifndef ONLINE_JUDGE
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
#endif
}
int main()
{
wj();
n=read(); m=read(); int p=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
add(x,y);
edg[i]=pii(x,y);
}
for(int i=1;i<=n;++i) val[i]=read();
int tot=1<<n;
for(int s=0;s<tot;++s)
{
int all=0;
for(int i=1;i<=n;++i) if(s&(1<<i-1)) vals[s]+=val[i],all++;
vals[s]=qpow(vals[s],p);
for(int i=1;i<=n;++i) fa[i]=i,deg[i]=0;
for(int i=1;i<=m;++i) if((s&(1<<edg[i].fi-1))&&(s&(1<<edg[i].se-1)))
{
deg[edg[i].fi]++; deg[edg[i].se]++;
int r1=find(edg[i].fi),r2=find(edg[i].se);
if(r1!=r2) all--;
fa[r1]=r2;
}
can[s]=1;
if(all!=1) continue;
for(int i=1;i<=n;++i) if(s&(1<<i-1))
if(deg[i]&1) {can[s]=1;break;}
else can[s]=0;
}
f[0][0]=1;
for(int s=0;s<tot;++s)
g[__builtin_popcount(s)][s]=can[s]*vals[s],vals[s]=qpow(vals[s],mod-2);
FWT(f[0],tot,1);
for(int i=1;i<=n;++i) FWT(g[i],tot,1);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=i;++j)
{
for(int k=0;k<tot;++k) f[i][k]=(f[i][k]+1ll*f[i-j][k]*g[j][k])%mod;
}
if(!p) continue;
FWT(f[i],tot,-1);
for(int k=0;k<tot;++k) f[i][k]=1ll*f[i][k]*vals[k]%mod;
FWT(f[i],tot,1);
}
FWT(f[n],tot,-1);
printf("%d\n",f[n][tot-1]);
return 0;
}
uoj348【WC2018】州区划分的更多相关文章
- UOJ348 WC2018 州区划分 状压DP、欧拉回路、子集卷积
传送门 应该都会判欧拉回路吧(雾 考虑状压DP:设\(W_i\)表示集合\(i\)的点的权值和,\(route_i\)表示点集\(i\)的导出子图中是否存在欧拉回路,\(f_i\)表示前若干个城市包含 ...
- [WC2018]州区划分——FWT+DP+FST
题目链接: [WC2018]州区划分 题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路.对于一种划分方案,第i个部分的 ...
- [WC2018]州区划分
[WC2018]州区划分 注意审题: 1.有序选择 2.若干个州 3.贡献是州满意度的乘积 枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0 存在欧拉回路:每个点都是偶度数,且图连通( ...
- [UOJ#348][WC2018]州区划分
[UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 ...
- [WC2018]州区划分(FWT,FST)
[WC2018]州区划分(FWT,FST) Luogu loj 题解时间 经典FST. 在此之前似乎用到FST的题并不多? 首先预处理一个子集是不是欧拉回路很简单,判断是否连通且度数均为偶数即可. 考 ...
- P4221 [WC2018]州区划分 无向图欧拉回路 FST FWT
LINK:州区划分 把题目中四个条件进行规约 容易想到不合法当前仅当当前状态是一个无向图欧拉回路. 充要条件有两个 联通 每个点度数为偶数. 预处理出所有状态. 然后设\(f_i\)表示组成情况为i的 ...
- [WC2018]州区划分(FWT)
题目描述 题解 这道题的思路感觉很妙. 题目中有一个很奇怪的不合法条件,貌似和后面做题没有什么关系,所以我们先得搞掉它. 也就是判断一个点集是否合法,也就是判断这个点集是否存在欧拉回路. 如果存在欧拉 ...
- Luogu4221 WC2018州区划分(状压dp+FWT)
合法条件为所有划分出的子图均不存在欧拉回路或不连通,也即至少存在一个度数为奇数的点或不连通.显然可以对每个点集预处理是否合法,然后就不用管这个奇怪的条件了. 考虑状压dp.设f[S]为S集合所有划分方 ...
- 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 ...
- [WC2018]州区划分(状压DP+FWT/FMT)
很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...
随机推荐
- Luogu2798 爆弹虐场 (二分,Kruskal)
二分答案,判定连通性 #include <iostream> #include <cstdio> #include <cstring> #include <a ...
- Luogu4408 [NOI2003]逃学的小孩 (树的直径)
一边一定是直径,另一边从两端点走取最小值的最大值 #include <iostream> #include <cstdio> #include <cstring> ...
- HC32L110 系列 M0 MCU 的介绍和Win10下DAP-Link, ST-Link, J-Link的烧录
HC32L110 系列 Cortex M0 MCU Hackaday 在三月份的时候介绍了一款最小的MCU NEW PART DAY: SMALLEST ARM MCU UPROOTS COMPETI ...
- 项目一共30个模块,你叫我maven版本一个个手动改?
大家好呀,我是铂赛东,一个乱入公众号博主的开源作者.今天分享一个maven小技巧,希望帮助到大家. 之前有个群友私聊问我,如何快速统一去更改项目中所有的maven版本号,他说之前都是手动一个个去修改, ...
- 1.2_Selenium的三生三世
- Java Web中MVC设计模式与IOC
MVC是由Model(模型).View(视图).Controller(控制器)三个模块组成 视图:用于做数据展示以及和用户交互的一个界面(html页面) 控制层:能够接受客户端的请求,具体的业务功能还 ...
- MixCSE:困难样本在句子表示中的使用
Unsupervised Sentence Representation via Contrastive Learning with Mixing Negatives 论文地址:https://www ...
- UE4自动打包工具编写
在UE的开发中,有些项目需要针对不同版本出不同的包,并有一个对应的GUI界面,供大家使用. 1.插件编写 先使用UE4自己的插件模板创建插件,做成插件形式 然后注册Slate UI,编写打开逻辑.并在 ...
- 002-ImageNetClassificationDeep2017
ImageNet classification with deep convolutional neural networks #paper 1. paper-info 1.1 Metadata Au ...
- 正点原子keilkill脚本
del *.bak /s del *.ddk /s del *.edk /s del *.lst /s del *.lnp /s del *.mpf /s del *.mpj /s del *.obj ...