pkusc 快到了……做点题涨涨 rp。

记 \(f(S,i)\) 表示 \(S\) 这个集合是决计不能选的(要么属于独立集,要么和独立集相连),或称已经考虑了的,\(i\) 表示此集合对应的最大独立集大小。那么枚举一下哪些点 \(j\) 不在 \(S\) 里,记 \(w_i\) 表示 \(i\) 和与之相邻的点集,则 \(f(S \cup w_j,i+1) \leftarrow f(S \cup w_j,i+1) + f(S,i) \times A_{n-|S|-1}^{|w_j-(w_j \cap S)|-1}\)。

然而对于一个集合 \(S\),它的最大独立集大小是确定的,那么就来一个数组 \(mx_S\) 来记录其最大独立集大小。当最大独立集大小更新之时,\(dp_S\) 就清零然后再计数就行了。复杂度从 \(O(\)跑得过\()\) 变成了 \(O(\)更跑得过\()\),也就是\(O(n^22^n)\) 变成了 \(O(n2^n)\)……。

改进前:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, w[25], uu, vv, jie[25], inv[25], dp[25][1050005], cnt[1050005];
const int mod=998244353;
int A(int x, int y){
// if(x<y) return 0;
return (ll)jie[x]*inv[x-y]%mod;
}
int main(){
cin>>n>>m;
for(int i=1; i<=m; i++){
scanf("%d %d", &uu, &vv);
uu--; vv--;
w[uu] |= 1<<vv;
w[vv] |= 1<<uu;
}
jie[0] = jie[1] = inv[0] = inv[1] = 1;
for(int i=2; i<=n; i++){
jie[i] = (ll)jie[i-1] * i % mod;
inv[i] = (ll)(mod - mod / i) * inv[mod%i] % mod;
}
for(int i=0; i<n; i++)
w[i] |= 1<<i;
for(int i=2; i<=n; i++)
inv[i] = (ll)inv[i-1] * inv[i] % mod;
for(int i=0; i<(1<<n); i++)
for(int j=0; j<n; j++)
if(i&(1<<j))
cnt[i]++;
dp[0][0] = 1;
for(int i=0; i<n; i++)
for(int s=0; s<(1<<n); s++)
if(dp[i][s])
for(int j=0; j<n; j++)
if(!(s&(1<<j)))
dp[i+1][s|w[j]] = (dp[i+1][s|w[j]] + (ll)dp[i][s] * A(n-cnt[s]-1, cnt[w[j]-(w[j]&s)]-1)%mod) % mod;
for(int i=n; i; i--)
if(dp[i][(1<<n)-1]){
cout<<(ll)dp[i][(1<<n)-1]*inv[n]%mod<<endl;
return 0;
}
return 0;
}

改进后:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, w[25], uu, vv, jie[25], inv[25], dp[1050005], cnt[1050005];
int mx[1050005];
const int mod=998244353;
int A(int x, int y){
// if(x<y) return 0;
return (ll)jie[x]*inv[x-y]%mod;
}
int main(){
cin>>n>>m;
for(int i=1; i<=m; i++){
scanf("%d %d", &uu, &vv);
uu--; vv--;
w[uu] |= 1<<vv;
w[vv] |= 1<<uu;
}
jie[0] = jie[1] = inv[0] = inv[1] = 1;
for(int i=2; i<=n; i++){
jie[i] = (ll)jie[i-1] * i % mod;
inv[i] = (ll)(mod - mod / i) * inv[mod%i] % mod;
}
for(int i=0; i<n; i++)
w[i] |= 1<<i;
for(int i=2; i<=n; i++)
inv[i] = (ll)inv[i-1] * inv[i] % mod;
for(int i=0; i<(1<<n); i++)
for(int j=0; j<n; j++)
if(i&(1<<j))
cnt[i]++;
dp[0] = 1;
for(int s=0; s<(1<<n); s++)
if(dp[s])
for(int i=0; i<n; i++)
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] = (dp[t] + (ll)dp[s] * A(n-cnt[s]-1, cnt[w[i]-(w[i]&s)]-1)%mod) % mod;
}
cout<<(ll)dp[(1<<n)-1]*inv[n]%mod<<endl;
return 0;
}

loj2540 「PKUWC 2018」随机算法的更多相关文章

  1. LOJ #2540. 「PKUWC 2018」随机算法(概率dp)

    题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...

  2. 「PKUWC 2018」随机算法 (第二版,正解做法)

    上一版貌似是打了 O(3 ^ N) 暴力和 一条链的情况,得了60分.... 第一次做的时候光想练一练暴力...就没去想正解,谁知道正解比暴力好写不知道多少,mmp 设 f(S) 为 选集合S中的点可 ...

  3. 「PKUWC 2018」随机算法 (60分部分分做法)

    明天就是CTSC的DAY 2了qwq,晚上敲敲暴力攒攒RP,果断随便看了个题就是打暴力hhhhh 前50% O(3^N) 暴力没什么好说的,我们设F[S][s]为已经选了S集合中的点,并且这个集合中的 ...

  4. LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)

    写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...

  5. LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)

    题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...

  6. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...

  7. loj2538 「PKUWC 2018」Slay the Spire

    pkusc 快到了--做点题涨涨 rp. ref我好菜啊QAQ. 可以发现期望只是一个幌子.我们的目的是:对于所有随机的选择方法(一共 \(\binom{2n}{m}\)种),这些选择方法都最优地打出 ...

  8. LOJ #2537. 「PKUWC 2018」Minimax (线段树合并 优化dp)

    题意 小 \(C\) 有一棵 \(n\) 个结点的有根树,根是 \(1\) 号结点,且每个结点最多有两个子结点. 定义结点 \(x\) 的权值为: 1.若 \(x\) 没有子结点,那么它的权值会在输入 ...

  9. 「PKUWC 2018」Minimax

    传送门:Here 一道线段树合并好题 如果要维护点$ x$的信息,相当于合并$ x$的两棵子树 对于这题显然有:任何叶子节点的权值都可能出现在其祖先上 因而我们只需要在线段树合并的时候维护概率即可 我 ...

随机推荐

  1. [转]Centos7 内核从3.10升级到4.12过程

    [原文地址] http://blog.csdn.net/youshijifen/article/details/73472434 [摘要] 近期,国家互联网应急中心漏洞(CNCERT)公告中提到Lin ...

  2. PHP 面向对象编程笔记 (麦子 php 第二阶段)

    类是把具有相似特性的对象归纳到一个类中,类就是一组相同属性和行为的对象的集合.类和对象的关系:类是相似对象的描述,先有类,再有对象.类是对象的抽象,对象是类的实例.通过class关键字创建类,成员属性 ...

  3. C语言学习记录_2019.01.29

    C语言的灵魂:指针 #include <stdio.h> int main(int argc, char **argv) {  printf("Hello, World!\n&q ...

  4. Mongoose模式的扩展

    模式的扩展 默认值 默认值的类型: 固定值.即使生成 代码展示: var mongoose = require('mongoose');mongoose.connect('mongodb://loca ...

  5. React 省市区三级联动

    省市区所对应的数据来自:http://www.zgguan.com/zsfx/jsjc/6541.html react中的代码是: export default class AddReceive ex ...

  6. WCF入门三[WCF宿主]

    一.概述 WCF程序必须在宿主上运行,也就是WCF服务必须寄宿在某一个windows的进程中,可以是IIS.控制台程序.窗体程序.WAS以及所有.net程序等程序进程中.在我用VS2013创建WCF服 ...

  7. LINUX系统配置相关

    修改系统引导文件 grub.cfg的文件位置   /boot/grub/grub.cfg set default="4"  默认windows是在第四个选项 set timeout ...

  8. Android之线程安全的单例模式,Adapter注意事项之引用传值

    线程安全的单例模式单位模式一般写法如下: public static FestivalLab mInstance; private FestivalLab() { } public static Fe ...

  9. AV Foundation 实现文字转语音

    AV Foundation 主要框架 CoreAudio 音频处理框架 扩展学习:<Learning CoreAudio> CoreVideo 视频处理的管道模式,逐帧访问 CoreMed ...

  10. iOS-合成图片(长图)

    合成图片 直接合成图片还是比较简单的,现在的难点是要把,通过文本输入的一些基本数据也合成到一张图片中,如果有多长图片就合成长图. 现在的实现方法是,把所有的文本消息格式化,然后绘制到一个UILable ...