UOJ 348 【WC2018】州区划分——子集卷积
参考:https://www.cnblogs.com/NaVi-Awson/p/9242645.html#%E5%AD%90%E9%9B%86%E5%8D%B7%E7%A7%AF
FMT就是快速莫比乌斯变换/反演,解决或卷积的问题,和 FWT 时间复杂度一样。
FWT定义了 \( a'[i]=\sum\limits_{j|i=i}a[j] \) ,利用倍增算出 a'[ ] 作为点值,相乘之后再算回去; FMT 也定义了这样的东西,但计算 a'[ ] 的方法是高维前缀和。
高维前缀和大概就是一维一维独立做前缀和。把每个二进制位看成取值只有 0 , 1 的一个维度,这样的前缀和就是子集的和;所以这一位是 1 的时候就累计上其他位和自己一样、这一位是 0 的那些数的答案;可以想到每个子集会在枚举到最高的与自己不同的位(如果是从低位到高位枚举的)的时候被计入。
FMT 从 a'[ ] 变回 a[ ] 的方法就是把刚才加的那些位置都减回去。如果加的时候是从低位到高位枚举,此时应该从高位到低位枚举;但仍从低位到高位枚举也没问题,大概和 FWT 那里的想法一样。
修改一下 FMT ,就能求子集卷积了。
子集卷积与或卷积的不同在于或起来的那两个数不能有交。
这个限制就通过使那两个数的 1 的个数加起来正好等于自己的 1 的个数来解决。
a[ i ][ S ]表示 1 的个数为 i 、S 的答案;如果 S 的 1 的个数不为 i ,这个值就是 0 ; a'[ i ][ S ] 表示 1 的个数为 i 、S 的所有子集的答案。有 \( c'[i][S]=\sum\limits_{j=0}^{i}a'[j][S]*b'[i-j][S] \) 。
从 a[ i ][ S ] 到 a'[ i ][ S ] 就是对于这个 i 做一遍高维前缀和。从 a'[ i ][ S ] 到 a[ i ][ S ] 就是把高维前缀和倒过来做一遍。
这道题的式子是 \( dp[i][S]*w^p[i][S] = \sum\limits_{j=0 , T\subseteq S}^{i-1}dp[j][T]*w^p[i-j][S-T] \) ,好在算 dp[ i ] 的时候用到的 dp[ j ] 的 j<i ,所以把 i 放在最外层枚举即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=,M=,K=(<<)+,mod=;
int n,m,p,hd[N],xnt,to[M],nxt[M];
int w[N][K],w2[K],dp[N][K],bin[N],ct[K];
bool ok[K],vis[N];
void upd(int &x){x>=mod?x-=mod:;}
int pw(int x,int k)
{int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;}
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void dfs(int cr,int fa,int s)
{
vis[cr]=;
for(int i=hd[cr],v;i;i=nxt[i])
if(!vis[v=to[i]]&&(s&bin[v-]))dfs(v,cr,s);
}
bool chk(int s)
{
for(int i=;i<=n;i++)
{
if(!(s&bin[i-]))continue; bool deg=;vis[i]=;
for(int j=hd[i];j;j=nxt[j])
if(s&bin[to[j]-])deg^=;
if(deg)return true;
}
int i;
for(i=;i<=n;i++)if(s&bin[i-]){dfs(i,,s);break;}
for(i++;i<=n;i++)if((s&bin[i-])&&!vis[i])return true;
return false;
}
void init()
{
bin[]=;for(int i=;i<=n;i++)bin[i]=bin[i-]<<;
for(int s=;s<bin[n];s++)ct[s]=ct[s-(s&-s)]+;///s from 1
for(int s=;s<bin[n];s++)ok[s]=chk(s);
}
void fmt(int *a,bool fx)
{
for(int i=;i<n;i++)
for(int s=;s<bin[n];s++)
if(s&bin[i])
(fx?a[s]+=mod-a[s^bin[i]]:a[s]+=a[s^bin[i]]),upd(a[s]);
}
int main()
{
n=rdn();m=rdn();p=rdn();
for(int i=,u,v;i<=m;i++)
u=rdn(),v=rdn(),add(u,v),add(v,u);
init();
for(int i=;i<=n;i++)w[][bin[i-]]=rdn();
for(int s=;s<bin[n];s++)w[ct[s]][s]=w[ct[s]-][s-(s&-s)]+w[][s&-s];
for(int s=;s<bin[n];s++)w[ct[s]][s]=pw(w[ct[s]][s],p);
for(int s=;s<bin[n];s++)w2[s]=pw(w[ct[s]][s],mod-);
for(int s=;s<bin[n];s++)if(!ok[s])w[ct[s]][s]=;//w2 is alright
dp[][]=;
for(int i=;i<=n;i++)
{
fmt(dp[i-],); fmt(w[i],);//i-j may =i
for(int j=;j<i;j++)
for(int s=;s<bin[n];s++)
dp[i][s]=(dp[i][s]+(ll)dp[j][s]*w[i-j][s])%mod;
fmt(dp[i],);
for(int s=;s<bin[n];s++)
if(ct[s]==i)dp[i][s]=(ll)dp[i][s]*w2[s]%mod;
else dp[i][s]=;
}
printf("%d\n",dp[n][bin[n]-]);
return ;
}
UOJ 348 【WC2018】州区划分——子集卷积的更多相关文章
- [UOJ#348][WC2018]州区划分
[UOJ#348][WC2018]州区划分 试题描述 小 \(S\) 现在拥有 \(n\) 座城市,第ii座城市的人口为 \(w_i\),城市与城市之间可能有双向道路相连. 现在小 \(S\) 要将这 ...
- [WC2018]州区划分
[WC2018]州区划分 注意审题: 1.有序选择 2.若干个州 3.贡献是州满意度的乘积 枚举最后一个州是哪一个,合法时候贡献sum[s]^p,否则贡献0 存在欧拉回路:每个点都是偶度数,且图连通( ...
- [WC2018]州区划分——FWT+DP+FST
题目链接: [WC2018]州区划分 题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路.对于一种划分方案,第i个部分的 ...
- [WC2018]州区划分(FWT,FST)
[WC2018]州区划分(FWT,FST) Luogu loj 题解时间 经典FST. 在此之前似乎用到FST的题并不多? 首先预处理一个子集是不是欧拉回路很简单,判断是否连通且度数均为偶数即可. 考 ...
- uoj#348/洛谷P4221 [WC2018]州区划分(FWT)
传送门(uoj) 传送门(洛谷) 全世界都会子集卷积就咱不会--全世界都在写\(FMT\)就咱只会\(FWT\)-- 前置芝士 或运算\(FWT\)或者\(FMT\) 左转洛谷模板区,包教包会 子集卷 ...
- UOJ348 WC2018 州区划分 状压DP、欧拉回路、子集卷积
传送门 应该都会判欧拉回路吧(雾 考虑状压DP:设\(W_i\)表示集合\(i\)的点的权值和,\(route_i\)表示点集\(i\)的导出子图中是否存在欧拉回路,\(f_i\)表示前若干个城市包含 ...
- [WC2018]州区划分(状压,子集卷积)
[洛谷题面]https://www.luogu.org/problemnew/show/P4221 首先考虑判定一个子图是否合法: (1)连通:并查集判断即可. (2)没有欧拉回路:存在欧拉回路的条件 ...
- P4221 [WC2018]州区划分 无向图欧拉回路 FST FWT
LINK:州区划分 把题目中四个条件进行规约 容易想到不合法当前仅当当前状态是一个无向图欧拉回路. 充要条件有两个 联通 每个点度数为偶数. 预处理出所有状态. 然后设\(f_i\)表示组成情况为i的 ...
- bzoj5153 [Wc2018]州区划分
题目链接 正解:子集和变换. 考场上只会暴力和$p=0$的情况,还只会$O(2^{n}*n^{3})$的. 然而这题题面出锅,导致考场上一直在卡裸暴力,后面的部分分没写了..听$laofu$说$O(2 ...
随机推荐
- HDU1978How Many Ways 记忆化dfs+dp
/*记忆化dfs+dp dp[i][j]代表达到这个点的所有路的条数,那么所有到达终点的路的总数就是这dp[1][1]加上所有他所能到达的点的 所有路的总数 */ #include<stdio. ...
- Git简介【转】
本文转载自:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 Git简介 Git是什 ...
- 【MVC - 参数原理】详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:http://www.cnblogs.com/fangjian0423/p/spring ...
- Bootstrap and Angular
- SDN原理 控制层 Controller控制器
本文参照SDN原理视频而成:SDN原理 Controller 概念 从上面这个图片,我们能够知道,Controller 是一个非常重要的东西:承上启下,左右拓展. 从整个SDN的架构来看,控制器 处在 ...
- 使用 p4-graphs 命令将p4程序依赖关系图形化
位置:/home/wasdns/p4factory/targets/l2_switch/p4src 命令: cd /home/wasdns/p4factory/targets/l2_switch/p4 ...
- HDU 4714 Treecycle(树形dp)
http://acm.hdu.edu.cn/showproblem.php?pid=4714 题意:给出一棵树,删除一条边和添加一条边的代价都是1,现在要把这棵树变成环,求需要花的最小代价. 思路: ...
- UVa 12169 不爽的裁判
https://vjudge.net/problem/UVA-12169 题意: 输入T,x1,x2,x3,...,x2T-1,输出x2,x4,...,x2T. 递推公式为xi=(axi-1+b)mo ...
- springboot2 统一异常处理
统一异常处理,不需要在每一层上单独捕获异常,只需要关注业务的开发: 代码如下: @RestControllerAdvice @Slf4j public class GlobalExceptionHan ...
- shell 脚本sed替换文件中某个字符串
有些大文件,特别的大.有几百兆,甚至更大. 用文本编辑器打开十分的费劲,电脑都卡死了. 想替换其中的字符串,很麻烦. 这个时候有了shell,简直强大到爆炸! # du -h user.sql 304 ...