*注意:题面请移步至loj查看。

  怎么PKU和THU都编了一些假算法,然后求正确率[汗]。

  之前听说PKUWC 2017考了五道dp,看来是真的。[完蛋.jpg]

  这三道题,2道概率,1道期望,和佬题组成一样。。。

  (我只是把PKUWC 2017在loj后3题做了,是不是全是Day 2就不知道了)

Problem A 随机算法

题目大意

  给定一个图。随机一个排列$p_{1}p_2p_3\cdots p_n$。假设当前有一个独立集集合$S$,从小到大枚举$i$,尝试将$p_i$加入$S$中。问得到最大独立集的概率。

  每个点有三个状态:被考虑其在独立集中,被考虑且不再独立集中,还未被考虑。

  设$f_S$表示,当独立集状态为$S$的概率。

  每次我们选择独立集中的点的时候,把新增加的不可能在独立集中的点在排列中的位置也考虑了。

  这样一个状态,我们就能表示上面三种点了。

  时间复杂度$O(n2^n)$

Code

  1 /**
  2  * loj
  3  * Problem#2540
  4  * Accepted
  5  * Time: 623ms
  6  * Memory: 10876k
  7  */
  8 #include <iostream>
  9 #include <cstdlib>
 10 #include <cstdio>
 11 using namespace std;
 12 typedef bool boolean;
 13 
 14 const int Mod = 998244353;
 15 
 16 const int N = 20, S = 1 << N;
 17 
 18 int add(int a, int b) {
 19     return ((a += b) >= Mod) ? (a - Mod) : (a);
 20 }
 21 
 22 int mul(int a, int b) {
 23     return a * 1ll * b % Mod;
 24 }
 25 
 26 void exgcd(int a, int b, int& x, int& y) {
 27     if (!b)
 28         x = 1, y = 0;
 29     else {
 30         exgcd(b, a % b, y, x);
 31         y -= (a / b) * x; 
 32     }
 33 }
 34 
 35 int inv(int a, int n) {
 36     int x, y;
 37     exgcd(a, n, x, y);
 38     return (x < 0) ? (x + n) : (x);
 39 }
 40 
 41 int n, m;
 42 int bit[S];
 43 int g[N], f[S];
 44 boolean indep[S];
 45 int fac[N], _fac[N], adj[S];
 46 
 47 inline void init() {
 48     scanf("%d%d", &n, &m);
 49     for (int i = 0, u, v; i < m; i++) {
 50         scanf("%d%d", &u, &v);
 51         --u, --v;
 52         g[u] |= (1 << v);
 53         g[v] |= (1 << u);
 54     }
 55 }
 56 
 57 int permu(int n, int m) {
 58     if (n < m)
 59         return 0;
 60     return mul(fac[n], _fac[n - m]);
 61 }
 62 
 63 inline void solve() {
 64     int all = 1 << n;
 65     indep[0] = true;
 66     for (int i = 1; i < all; i++)
 67         for (int j = 0; j < n && !indep[i]; j++)
 68             if (((i >> j) & 1) && indep[i ^ (1 << j)] && !(g[j] & i))
 69                 indep[i] = true;
 70     
 71     for (int i = 1; i < all; i++)
 72         bit[i] = bit[i >> 1] + (i & 1);
 73     
 74     int mx = 0;
 75     for (int i = 1; i < all; i++)
 76         if (indep[i] && bit[i] > mx)
 77             mx = bit[i];
 78         
 79     adj[0] = 0;
 80     for (int i = 1; i < all; i++)
 81         for (int j = 0; j < n && !adj[i]; j++)
 82             if ((i >> j) & 1)
 83                 adj[i] = adj[i ^ (1 << j)] | g[j];    
 84 
 85     fac[0] = 1;
 86     for (int i = 1; i <= n; i++)
 87         fac[i] = mul(fac[i - 1], i);
 88     _fac[n] = inv(fac[n], Mod);
 89     for (int i = n; ~i; i--)
 90         _fac[i - 1] = mul(_fac[i], i);
 91     
 92     f[0] = 1;
 93     for (int s = 0; s < all - 1; s++) {
 94         if (!f[s] || !indep[s])
 95             continue;
 96         int ban = adj[s] | s;
 97         for (int i = 0; i < n; i++) {
 98             if (((ban >> i) & 1))
 99                 continue;
100             f[s | (1 << i)] = add(f[s | (1 << i)], mul(f[s], permu(n - bit[ban] - 1, bit[g[i]] - bit[ban & g[i]])));
101         }
102     }
103     int res = 0;
104     for (int i = 1; i < all; i++)
105         if (indep[i] && bit[i] == mx)
106             res = add(res, f[i]);
107     res = mul(res, _fac[n]);
108     printf("%d\n", res);
109 }
110 
111 int main() {
112     init();
113     solve();
114     return 0;
115 }
Problem A

相关文章: