[LOJ#2540][PKUWC2018]随机算法(概率DP)
场上数据很水,比较暴力的做法都可以过90分以上,下面说几个做法。
1. 暴力枚举所有最大独立集,对每个独立集分别DP。复杂度玄学,但是由于最大独立集并不多,所以可以拿90.
2. dp[S][k]表示考虑到排列的第k位,当前独立集为S的方案数,枚举第k+1位,根据是否与S相连转移到dp[S][k+1]或dp[S | a[k+1]][k+1]。$O(n^22^n)$
3. dp[S]表示排列的状态为S时的正确率,mx[S]表示排列状态为S时能得到的最大独立集大小,考虑转移,枚举排列里最后一个在独立集中的点i∈S,从S中删去所有与i相连的点得到S',若mx[S]<mx[S']+1则更新mx[S],dp[S]清零,否则累加。注意到每个排列都是等概率出现的,所以最后直接除以|S|即可。 $O(n2^n)$
方法一:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define ll long long
using namespace std; const int N=<<,mod=;
ll n,m,x,y,s[],p[],f[N][],cnt,mx,v[N],num[N],t[N],ans,o[N]; int main(){
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
scanf("%lld%lld",&n,&m);
p[]=; rep(i,,n) p[i]=p[i-]<<;
rep(i,,m) scanf("%lld%lld",&x,&y),s[x]|=p[y],s[y]|=p[x];
cnt=(<<n)-; f[][]=;
rep(i,,cnt){
ll tmp=; v[i]=;
rep(j,,n) if ((i&p[j])&&(s[j]&i)) v[i]=;
if (v[i]){
rep(j,,n) if (i&p[j]) tmp++,t[i]|=s[j];
num[i]=tmp; mx=max(mx,tmp);
tmp=;
rep(j,,n) if (t[i]&p[j]) tmp++;
o[i]=tmp;
}
}
rep(i,,cnt) if (v[i])
rep(j,,o[i]){
if (j!=o[i]) f[i][j+]=(f[i][j+]+f[i][j]*(o[i]-j))%mod;
rep(k,,n) if (!(i&p[k])&&!(p[k]&t[i])) f[i|p[k]][j]=(f[i|p[k]][j]+f[i][j])%mod;
if (num[i]==mx && j==o[i]) ans=(ans+f[i][j])%mod;
}
printf("%lld\n",ans);
return ;
}
方法二:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define P 998244353
#define N 21
#define t (1<<n)
int n,m;
long long ans=;
bool flag[<<(N-)];
int s[<<(N-)],w[N],v[<<(N-)],cnt[<<(N-)],tot[<<(N-)],f[][<<(N-)],maximum=;
int main()
{
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
n=read(),m=read();
for (int i=;i<=n;i++) w[i]=<<(i-),s[w[i]]=w[i];
for (int i=;i<=m;i++)
{
int x=read(),y=read();
s[w[x]]|=w[y],s[w[y]]|=w[x];
}
flag[]=;
for (int i=;i<t;i++)
if (flag[i])
for (int j=;j<=n;j++)
if (!(w[j]&s[i]))
{
flag[i|w[j]]=,s[i|w[j]]=s[i]|s[w[j]],cnt[i|w[j]]=cnt[i]+;
if (cnt[i]>=maximum) maximum=cnt[i|w[j]];
}
for (int i=;i<t;i++)
{
s[i]=(~s[i])&(t-);
register int k=s[i];
while (k) k^=k&-k,tot[i]++;
v[i]=i&-i;
}
f[][]=;
for (register int i=;i<n;i++)
for (register int j=;j<t;j++)
if (f[i][j])
{
for (register int k=s[j];k;k^=v[k])
f[i+][j|v[k]]=(f[i+][j|v[k]]+f[i][j])%P;
f[i+][j]=(1ll*f[i][j]*(n-i-tot[j])+f[i+][j])%P;
}
for (int i=;i<t;i++) if (cnt[i]==maximum) ans=(ans+f[n][i])%P;
cout<<ans;
fclose(stdin);fclose(stdout);
return ;
}
方法三:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
typedef long long ll;
using namespace std; const int N=,mod=;
int n,m,x,y,inv[N],f[N],mx[<<N],F[<<N]; int main(){
scanf("%d%d",&n,&m);
rep(i,,m) scanf("%d%d",&x,&y),x--,y--,f[x]|=<<y,f[y]|=<<x;
inv[]=; f[]|=; F[]=;
rep(i,,n) f[i-]|=(<<(i-)),inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
for (int i=; i<(<<n); i++){
int tot=;
for (int j=; j<n; j++) if (i&(<<j)){
int s=i&(~f[j]);
if (mx[i]<mx[s]+) mx[i]=mx[s]+,F[i]=;
if (mx[i]==mx[s]+) F[i]=(F[i]+F[s])%mod;
tot++;
}
F[i]=1ll*F[i]*inv[tot]%mod;
}
printf("%d\n",F[(<<n)-]);
return ;
}
[LOJ#2540][PKUWC2018]随机算法(概率DP)的更多相关文章
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- 【洛谷5492】[PKUWC2018] 随机算法(状压DP)
点此看题面 大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集.求这个随机算法的 ...
- [PKUWC2018]随机算法
题意:https://loj.ac/problem/2540 给定一个图(n<=20),定义一个求最大独立集的随机化算法 产生一个排列,依次加入,能加入就加入 求得到最大独立集的概率 loj25 ...
- [LOJ2540] [PKUWC2018] 随机算法
题目链接 LOJ:https://loj.ac/problem/2540 Solution 写的时候脑子不太清醒码了好长然后时间\(LOJ\)垫底... 反正随便状压\(dp\)一下就好了,设\(f[ ...
- LOJ #2542 [PKUWC2018]随机游走 (概率期望、组合数学、子集和变换、Min-Max容斥)
很好很有趣很神仙的题! 题目链接: https://loj.ac/problem/2542 题意: 请自行阅读 题解首先我们显然要求的是几个随机变量的最大值的期望(不是期望的最大值),然后这玩意很难求 ...
- LOJ2540 PKUWC2018 随机算法 状压DP
传送门 两种$DP$: ①$f_{i,j}$表示前$i$次选择,最大独立集为$j$时达到最大独立集的方案总数,转移:$a.f_{i,j}+=f_{i+1,j+2^k}$(保证$k$加入后符合条件):$ ...
- LOJ2540 [PKUWC2018] 随机算法 【状压DP】
题目分析: 听说这题考场上能被$ O(4^n) $的暴力水过,难不成出题人是毕姥爷? 首先思考一个显而易见的$ O(n^2*2^n) $的暴力DP.一般的DP都是考虑最近的加入了哪个点,然后删除后递归 ...
- [BZOJ5006][LOJ#2290][THUWC2017]随机二分图(概率+状压DP)
https://loj.ac/problem/2290 题解:https://blog.csdn.net/Vectorxj/article/details/78905660 不是很好理解,对于边(x1 ...
- LG5492 [PKUWC2018]随机算法
题意 有一种贪心求最大独立集的算法: 随机一个排列 按顺序加入独立集,如果一个点能加入,就加入\({S}\) 给出一张图,问得出正确答案的概率. \(n \leq 20\) 传送门 思路 用 \(dp ...
随机推荐
- 【BZOJ 1407】[Noi2002]Savage ExGCD
我bitset+二分未遂后就来用ExGCD了,然而这道题的时间复杂度还真是玄学...... 我们枚举m然后对每一对用ExGCD判解,我们只要满足在最小的一方死亡之前无解就可以了,对于怎么用,就是ax+ ...
- BZOJ2631 tree(伍一鸣) LCT 秘制标记
这个题一看就是裸地LCT嘛,但是我wa了好几遍,这秘制标记...... 注意事项:I.*对+有贡献 II.先下传*再下传+(因为我们已经维护了+,不能再让*对+产生贡献)III.维护+用到size # ...
- 面试前需要弄懂的SQL
说明:创建数据库 view source print? 1 Create DATABASE database-name 说明:删除数据库 view source print? 1 drop d ...
- canvas知识01
本文转自:http://www.cnblogs.com/jsdarkhorse/archive/2012/06/29/2568451.html 更多参考:http://www.cnblogs.com/ ...
- 调用webservice接口
这里是cxf服务器,采用myeclipse6.5,把wsdl放到本地的方式. 新建一个包, 把解析到的类放在这个包下面. 生成的代码结构: 调用: public static String callI ...
- 动态规划:LCIS
先给出状态转移方程: 定义状态 F[i][j]表示以a串的前i个整数与b串的前j个整数且以b[j]为结尾构成的LCIS的长度 状态转移方程: ①F[i][j] = F[i-][j] (a[i] != ...
- centos6.4 nginx+mysql+php整合phpmyadmin出错解决方案
今天在centos下整合phpmyadmin出错,错误提示如下: Error during session start; please check your PHP and/or webserver ...
- bzoj 1880 最短路
我们首先知道,答案肯定是最短路图中的某段公共链,那么设(x,y)为x到y的最短路,那么答案为((s1,t1)+(s2,t2)-min((s1,s2)+(t1,t2),(s1,t2),(s2,t1))) ...
- Sublime Text 3 遇到的一些小坑的解决方法
1.[不停弹出更新框]Sublime Text 3 软件会弹出“Update Available”对话框,点击“Cancel”按钮取消:取消之后还是会频繁出现 解决方法:点击菜单栏“Preferenc ...
- <script>中的async与defer属性
1.script元素中的defer属性 1.1说明 使用该属性可以使脚本延迟到文档完全被解析和显示之后再按照原本的顺序执行,即告诉浏览器立即下载脚本,但延迟执行,该属性只对外部脚本有效 1.2使用方法 ...