传送门

完了pkuwc咋全是dp怕是要爆零了……

设\(f(S)\)表示\(S\)的排列数,\(S\)为不能再选的点集(也就是选到独立集里的点和与他们相邻的点),\(mx(S)\)表示\(S\)状态下对应的独立集大小,枚举点\(i\),如果\(i\)不在\(S\)里,分情况考虑,设\(w[i]\)表示点\(i\)以及与之相邻的点,\(T=S|w[i]\),\(sz[S]\)表示二进制\(S\)有多少个\(1\),如果\(mx[T]=mx[S]+1\),那么$$f[T]+=f[S]\times A_{n-sz[S]-1}^{sz[w[i]-(w[i]&S)]-1}$$

上式的意思是,为了把\(i\)选进来,要把所有的与\(i\)相邻的点(除已经在\(S\)里的)都放到\(i\)的后面,那么共有\(n-sz[S]-1\)个位置,要放\(sz[w[i]-(w[i]\&S)]-1\)个数,就是一个排列

如果\(mx[T]<mx[S]+1\),那么先把\(f[T]\)清零,然后按上面更新就是了

//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=(1<<20)+5,P=998244353;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
return res;
}
int fac[25],inv[25],w[25],sz[N],dp[N],mx[N];
int n,m,u,v,lim;
inline int A(R int n,R int m){return mul(fac[n],inv[n-m]);}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read(),lim=(1<<n);
while(m--)u=read()-1,v=read()-1,w[u]|=(1<<v),w[v]|=(1<<u);
fp(i,0,n-1)w[i]|=(1<<i);
fp(i,1,lim-1)sz[i]=sz[i>>1]+(i&1);
fac[0]=inv[0]=fac[1]=inv[1]=1;
fp(i,2,n)fac[i]=mul(fac[i-1],i);
inv[n]=ksm(fac[n],P-2);
fd(i,n-1,2)inv[i]=mul(inv[i+1],i+1);
dp[0]=1;
fp(S,0,lim-1)if(dp[S]){
fp(i,0,n-1)if(!(S&(1<<i))){
int T=S|w[i];
if(mx[T]<mx[S]+1)mx[T]=mx[S]+1,dp[T]=0;
if(mx[T]==mx[S]+1)dp[T]=add(dp[T],mul(dp[S],A(n-sz[S]-1,sz[w[i]-(w[i]&S)]-1)));
}
}printf("%d\n",mul(dp[lim-1],inv[n]));
return 0;
}

loj#2540. 「PKUWC2018」随机算法的更多相关文章

  1. 【LOJ】 #2540. 「PKUWC2018」随机算法

    题解 感觉极其神奇的状压dp \(dp[i][S]\)表示答案为i,然后不可选的点集为S 我们每次往答案里加一个点,然后方案数是,设原来可以选的点数是y,新加入一个点后导致了除了新加的点之外x个点不能 ...

  2. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  3. 【LOJ2540】「PKUWC2018」随机算法

    题意 题面 给一个 \(n\) 个点 \(m\) 条边的无向图.考虑如下求独立集的随机算法:随机一个排列并按顺序加点.如果当前点能加入独立集就加入,否则不加入.求该算法能求出最大独立集的概率. \(n ...

  4. LOJ #2542「PKUWC2018」随机游走

    $ Min$-$Max$容斥真好用 $ PKUWC$滚粗后这题一直在$ todolist$里 今天才补掉..还要更加努力啊.. LOJ #2542 题意:给一棵不超过$ 18$个节点的树,$ 5000 ...

  5. LOJ 2542 「PKUWC2018」随机游走 ——树上高斯消元(期望DP)+最值反演+fmt

    题目:https://loj.ac/problem/2542 可以最值反演.注意 min 不是独立地算从根走到每个点的最小值,在点集里取 min ,而是整体来看,“从根开始走到点集中的任意一个点就停下 ...

  6. LOJ2540. 「PKUWC2018」随机算法【概率期望DP+状压DP】

    LINK 思路 首先在加入几个点之后所有的点都只有三种状态 一个是在独立集中,一个是和独立集联通,还有一个是没有被访问过 然后前两个状态是可以压缩起来的 因为我们只需要记录下当前独立集大小和是否被访问 ...

  7. loj#2542. 「PKUWC2018」随机游走(MinMax容斥 期望dp)

    题意 题目链接 Sol 考虑直接对询问的集合做MinMax容斥 设\(f[i][sta]\)表示从\(i\)到集合\(sta\)中任意一点的最小期望步数 按照树上高斯消元的套路,我们可以把转移写成\( ...

  8. 「PKUWC2018」随机算法

    题目 思博状压写不出是不是没救了呀 首先我们直接状压当前最大独立集的大小显然是不对的,因为我们的答案还和我们考虑的顺序有关 我们发现最大独立集的个数好像不是很多,可能是\(O(n)\)级别的,于是我们 ...

  9. loj2540 「PKUWC2018」随机算法 【状压dp】

    题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i] ...

随机推荐

  1. FSB总线、HT总线、QPI总线、DMI总线

    http://wenku.baidu.com/link?url=d0NQFyvVpU--FpQUIjkPcdE036riitKgKib3385qr7VdB1oNUcIDpRndY-HH4ITjzJln ...

  2. 杭电 2176 取(m堆)石子游戏(博弈)

    取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. atitit.eclipse有多少api&#160;&#160;扩展点,以及扩展点的设计

    atitit.eclipse有多少api  扩展点,以及扩展点的设计 不赞成使用的.作废的以及内部的扩展点 [扩展]页显示了几个你不应该在你的插件中使用的扩展点.在附表C.1的[描写叙述]栏中.我们使 ...

  4. Understanding When to use RabbitMQ or Apache Kafka Kafka RabbitMQ 性能对比

    Understanding When to use RabbitMQ or Apache Kafka https://content.pivotal.io/rabbitmq/understanding ...

  5. 使用libcurl的包装库cpr发起http请求

    cpr GitHub地址https://github.com/whoshuu/cpr 简单示例:cpr_http_request.cpp #include <iostream> #incl ...

  6. SpringMvc參数的接受以及serializeArray的使用方法

    需求:从页面提交一个table中的数据到后台,通经常使用于批量改动 把全部的数据到放到 input属性中,设置name定义成为对象的相关属性,使用Jquery的serializeArray这种方法封装 ...

  7. 百度自然语言处理api用法

    def words url = "https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?access_token=1111111" param ...

  8. 一个实用的UIView的类别

    // // FrameAccessor.h // FrameAccessor // // Created by Alex Denisov on 18.03.12. // Copyright (c) 2 ...

  9. 为了cider,尝试emacs的坑

    https://github.com/clojure-emacs/cider http://clojure-doc.org/articles/tutorials/emacs.html emacs通过b ...

  10. 解决virtualbox安装增强工具失败的问题

    virtualbox有个增强工具,安装之后用户体验是非常爽的.但是有些时候在安装增强工具会遇到一些小问题,无非是没有安装gcc,make之类的编译工具或是需要安装kernel*.而我遇到的问题在做了这 ...