zoukankan      html  css  js  c++  java
  • LOJ#2540 随机算法

    题意:给定图,随机一个排列,依次加点,如果加点之后不是独立集就不加。求最后得到一个最大独立集的概率。

    解:就是求有多少个排列可以加出最大独立集。

    显然有一个3n的状压DP,0表示没加,1表示没加上,2表示加上了。

    转移的时候枚举下一个加哪个点即可。这样有30分。

    然后还是过不了的。考虑怎么压成二进制。我们可以用1表示这个点不能加(与某个加入的点相邻或者已经加入),0表示这个点可以加。

    这样会损失一个信息,你就不知道当前独立集多大。所以再开一维表示独立集大小。

    每次转移的时候考虑加哪一个点。顺便把它相邻的点也加上。注意它相邻的点加入的时候有顺序。具体来说,我们之前的状态中如果有x个点,那么就还有n - x个空位。而其中最前面的一个空位肯定是你主动加进去的点。所以现在要在n - x - 1个空位中放进被动加进去的点。这就是一个排列数。

    然后就有了一个n2n的DP了。注意预处理出与一个点相邻的点和一个状态中点的个数。

      1 #include <cstdio>
      2 
      3 typedef long long LL;
      4 const int N = 21;
      5 const LL MO = 998244353;
      6 
      7 struct Edge {
      8     int nex, v;
      9 }edge[N * N * 2]; int top;
     10 
     11 int n, e[N], cnt[1 << 20], nb[N];
     12 LL f[N][1 << 20], nn[N], inv[N], invn[N];
     13 bool vis[N];
     14 
     15 inline void add(int x, int y) {
     16     top++;
     17     edge[top].v = y;
     18     edge[top].nex = e[x];
     19     e[x] = top;
     20     return;
     21 }
     22 
     23 inline void out(int x) {
     24     for(int i = 0; i < n; i++) {
     25         printf("%d", (x >> i) & 1);
     26     }
     27     return;
     28 }
     29 
     30 inline LL C(int n, int m) {
     31     return nn[n] * invn[m] % MO * invn[n - m] % MO;
     32 }
     33 inline LL P(int n, int m) {
     34     if(m > n) {
     35         return 0;
     36     }
     37     return nn[n] * invn[n - m] % MO;
     38 }
     39 
     40 int main() {
     41     int m;
     42     scanf("%d%d", &n, &m);
     43     for(int i = 1, x, y; i <= m; i++) {
     44         scanf("%d%d", &x, &y);
     45         add(x, y);
     46         add(y, x);
     47     }
     48     int lm = (1 << n);
     49     for(int s = 1; s < lm; s++) {
     50         cnt[s] = 1 + cnt[(s - (s & (-s))) >> 1];
     51     }
     52     for(int x = 0; x < n; x++) {
     53         nb[x] = 1 << x;
     54         for(int i = e[x + 1]; i; i = edge[i].nex) {
     55             int y = edge[i].v - 1;
     56             nb[x] |= (1 << y);
     57         }
     58     }
     59     nn[0] = inv[0] = invn[0] = 1;
     60     nn[1] = inv[1] = invn[1] = 1;
     61     for(int i = 2; i <= n; i++) {
     62         nn[i] = nn[i - 1] * i % MO;
     63         inv[i] = inv[MO % i] * (MO - MO / i) % MO;
     64         invn[i] = invn[i - 1] * inv[i] % MO;
     65     }
     66 
     67     int ans = 0;
     68     LL sum = 0;
     69     f[0][0] = vis[0] = 1;
     70     for(int i = 0; i <= n && vis[i]; i++) {
     71         for(int s = 0; s < lm; s++) {
     72             // f[i][s]
     73             if(!f[i][s]) {
     74                 continue;
     75             }
     76             //printf("f %d ", i); out(s); printf(" = %lld 
    ", f[i][s]);
     77             if(i > ans) {
     78                 ans = i;
     79                 sum = f[i][s];
     80             }
     81             else if(i == ans) {
     82                 sum = (sum + f[i][s]) % MO;
     83             }
     84             for(int j = 0; j < n; j++) {
     85                 if((s >> j) & 1) {
     86                     continue;
     87                 }
     88                 int t = s | nb[j];
     89                 // f[i + 1][t]
     90                 (f[i + 1][t] += f[i][s] * P(n - cnt[s] - 1, cnt[t] - cnt[s] - 1) % MO) %= MO;
     91                 vis[i + 1] = 1;
     92                 //printf("f %d ", i + 1); out(t); printf(" += f %d ", i); out(s); printf(" * %lld 
    ", P(n - cnt[s] - 1, cnt[t] - cnt[s] - 1));
     93             }
     94         }
     95     }
     96 
     97     printf("%lld
    ", sum * invn[n] % MO);
     98     //printf("%d %lld 
    ", ans, sum);
     99     return 0;
    100 }
    AC代码
  • 相关阅读:
    OpenVINO Model Server的服务化部署——step3(django服务构建)
    (5)名称空间 namespace 和 using 声明
    (4)#include 指令
    (3)注释
    (2)简单的程序
    (1)Hello World
    javaScript 错误学习 -- throw、try 、catch和 finally
    js 如何在数字前面自动补零,生成序列号、单据号
    vs2015项目运行出现“无法启动IIS Express Web服务器”,如何解决
    Sql Server 2008 如何将数据表导出Excel文件?
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10374257.html
Copyright © 2011-2022 走看看