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. 微信小程序 嵌套循环

    前言 入门教程之列表渲染多层嵌套循环,目前官方的文档里,主要是一维数组列表渲染的案例,还是比较简单单一,给刚入门的童鞋还是无从入手的感觉. <view wx:for="{{items} ...

  2. YII2.0 获取当前访问地址/IP信息

    假设我们当前页面的访问地址是:http://localhost/CMS/public/index.php?r=news&id=1 一. 1.获取当前域名:echo Yii::app()-> ...

  3. php 操作RabbitMQ

    本文摘抄自:https://www.cnblogs.com/alin-qu/p/8312874.html php 操作RabbitMQ   基本流程图 如果exchange 没有绑定queue,则消息 ...

  4. (转)Updates were rejected because the tip of your current branch is behind

    刚创建的github版本库,在push代码时出错: $ git push -u origin masterTo git@github.com:******/Demo.git ! [rejected] ...

  5. error:control reaches end of non-void function [-Werror=return-type]

    在做LeetCode上的题目时,出现了这个错误, 原代码如下: class Solution { public: vector<int> twoSum(vector<int>& ...

  6. 【Leetcode】605. Can Place Flowers

    Description Suppose you have a long flowerbed in which some of the plots are planted and some are no ...

  7. 高德API+Python解决租房问题(.NET版)

    源码地址:https://github.com/liguobao/58HouseSearch 在线地址:58公寓高德搜房(全国版):http://codelover.link:8080/ 周末闲着无事 ...

  8. C++学习010-将某个地址转化为指针

    如果需要将某个具体的地址转化为指针,可以直接使用类型那个转换来是实现. 实例如下 int main() { void* pData = (void*)(0x004001); std::cout < ...

  9. LeetCode - 67. Add Binary(4ms)

    Given two binary strings, return their sum (also a binary string). The input strings are both non-em ...

  10. sqlserver2012 查询远程数据库

    EXEC sp_addlinkedserver 'LinkName','','SQLOLEDB','121.43.177.236'EXEC sp_addlinkedsrvlogin 'LinkName ...