zoukankan      html  css  js  c++  java
  • BZOJ 2560 及其加强

    有$n$个点,在$i,j$两个点之间连边的方案数有$c_{i,j}$种,也可以不连。求不同的连通导出子图个数(即有多少种连边方案使得整个图连通)。

    $$nle16$$

    加强:

    $$nle20$$

    令$g_S$为点集$S$的导出子图个数,$f_S$为点集$S$的连通导出子图个数。特别地,$f_{varnothing}=g_{varnothing}=0$。

    $g$是好求的,由定义知

    $$g_S=prod_{i,jin S}c_{i,j}+1$$

    可以$O(n2^n)$求。

    考虑怎么求$f$,在$nle16$时,直接子集$ ext{dp}$算不连通导出子图个数即可,即

    $$f_S=g_S-sum_{1 in T land T subset S}f_Tg_{Ssetminus T}$$

    时间复杂度$O(3^n)$。

    但在$n$更大的时候,这个复杂度是不可接受的。

    考虑集合幂级数,定义乘法为子集卷积,则

    $$1+g=sum_{kge0}frac{f^k}{k!}$$

    $$1+g=e^f$$

    转换一下,得

    $$f=ln(1+g)$$

    那么对$g$做$ ext{FMT}$之后对每一项暴力递推求$ln$即可。

    时间复杂度$O(n^22^n)$。

      1 #include <bits/stdc++.h>
      2 
      3 #define IL __inline__ __attribute__((always_inline))
      4 
      5 #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
      6 #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
      7 #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
      8 #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
      9 
     10 typedef long long LL;
     11 
     12 template <class T>
     13 IL bool chkmax(T &a, const T &b) {
     14   return a < b ? ((a = b), 1) : 0;
     15 }
     16 
     17 template <class T>
     18 IL bool chkmin(T &a, const T &b) {
     19   return a > b ? ((a = b), 1) : 0;
     20 }
     21 
     22 template <class T>
     23 IL T mymax(const T &a, const T &b) {
     24   return a > b ? a : b;
     25 }
     26 
     27 template <class T>
     28 IL T mymin(const T &a, const T &b) {
     29   return a < b ? a : b;
     30 }
     31 
     32 template <class T>
     33 IL T myabs(const T &a) {
     34   return a > 0 ? a : -a;
     35 }
     36 
     37 const int INF = 0X3F3F3F3F;
     38 const double EPS = 1E-8, PI = acos(-1.0);
     39 
     40 #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
     41 #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
     42 
     43 const int MASK = 20, MOD = 1000000007;
     44 
     45 IL int add(int a, int b) {
     46   a += b;
     47   return a >= MOD ? a - MOD : a;
     48 }
     49 
     50 IL int sub(int a, int b) {
     51   a -= b;
     52   return a < 0 ? a + MOD : a;
     53 }
     54 
     55 IL int mul(int a, int b) {
     56   return (LL)a * b % MOD;
     57 }
     58 
     59 IL int quickPow(int a, int p) {
     60   int result = 1;
     61   for (; p; p >>= 1, a = mul(a, a)) {
     62     if (p & 1) {
     63       result = mul(result, a);
     64     }
     65   }
     66   return result;
     67 }
     68 
     69 typedef int PowerSeries[MASK + 1];
     70 
     71 PowerSeries f[1 << MASK];
     72 int g[1 << MASK], val[MASK][MASK], inv[MASK + 1], n;
     73 
     74 IL void add(PowerSeries &a, const PowerSeries &b) {
     75   For(i, 0, n) {
     76     a[i] = add(a[i], b[i]);
     77   }
     78 }
     79 
     80 IL void sub(PowerSeries &a, const PowerSeries &b) {
     81   For(i, 0, n) {
     82     a[i] = sub(a[i], b[i]);
     83   }
     84 }
     85 
     86 IL void FMT(PowerSeries *f) {
     87   FOR(i, 0, n) {
     88     FOR(S, 0, 1 << n) {
     89       if (S & (1 << i)) {
     90         add(f[S], f[S ^ (1 << i)]);
     91       }
     92     }
     93   }
     94 }
     95 
     96 IL void IFMT(PowerSeries *f) {
     97   FOR(i, 0, n) {
     98     FOR(S, 0, 1 << n) {
     99       if (S & (1 << i)) {
    100         sub(f[S], f[S ^ (1 << i)]);
    101       }
    102     }
    103   }
    104 }
    105 
    106 IL void ln(PowerSeries &f) {
    107   PowerSeries tp;
    108   memcpy(tp, f, sizeof f);
    109   FOR(i, 1, n) {
    110     int cur = 0;
    111     FOR(j, 0, i) {
    112       cur = add(cur, mul(j + 1, mul(f[j + 1], tp[i - j])));
    113     }
    114     cur = mul(cur, inv[i + 1]);
    115     f[i + 1] = sub(f[i + 1], cur);
    116   }
    117 }
    118 
    119 int main() {
    120   scanf("%d", &n);
    121   For(i, 1, n) {
    122     inv[i] = quickPow(i, MOD - 2);
    123   }
    124   FOR(i, 0, n) {
    125     FOR(j, 0, n) {
    126       scanf("%d", &val[i][j]);
    127       val[i][j] = add(val[i][j], 1);
    128     }
    129   }
    130   g[0] = 1;
    131   FOR(S, 1, 1 << n) {
    132     int last = 0;
    133     FOR(i, 0, n) {
    134       if (S & (1 << i)) {
    135         last = i;
    136       }
    137     }
    138     g[S] = g[S - (1 << last)];
    139     FOR(i, 0, last) {
    140       if (S & (1 << i)) {
    141         g[S] = mul(g[S], val[i][last]);
    142       }
    143     }
    144     f[S][__builtin_popcount(S)] = g[S];
    145   }
    146   g[0] = 0;
    147   FMT(f);
    148   FOR(i, 0, 1 << n) {
    149     ln(f[i]);
    150   }
    151   IFMT(f);
    152   printf("%d
    ", f[(1 << n) - 1][n]);
    153   return 0;
    154 }
  • 相关阅读:
    【NOIp复习】欧拉函数
    【vijos】【神读入】Knights
    【vijos】【位运算】Miku_Nobody
    【vijos】【二分图带权匹配】拯救世界-星际大战
    【模板】KM算法模板(带注释)——二分图带权最大匹配
    【vijos】【二分图最大匹配】银翼の舞
    【vijos】【树形dp】佳佳的魔法药水
    QuartusII 13.0的完美破解
    CANVAS实现调色板 之 我的第一个随笔
    Couldn't read row 0, col -1 from CursorWindow
  • 原文地址:https://www.cnblogs.com/sjkmost/p/10801937.html
Copyright © 2011-2022 走看看