首页 > 其他分享 >ABC253Ex We Love Forest

ABC253Ex We Love Forest

时间:2022-10-14 22:34:38浏览次数:52  
标签:inline return int ABC253Ex Forest mathcal Love po Mod

容易发 \(i\) 条边的森林,有 \(n-i\) 棵树,那么有:

令 \(g_k(S)\) 表示点集 \(S\) 形成含有 \(k\) 棵树的森林的方案数

答案为: \(\displaystyle \frac{g_{n-i}(U)i!}{m^i}\)

可以枚举 \(S\) 中任意点所在的树转移,那么记 \(f(S)\) 表示点集 \(S\) 连成树的方案数,有:

\[g_i(S)=\sum_{T \subseteq S}f(T)g_{i-1}(S-T) \]

那么可以 \(\mathcal O(n3^n)\) 计算所有 \(g_i(S)\) ,当然可以使用子集卷积做到 \(\mathcal O(n^32^n)\)

现在问题转化为求 \(f(S)\),当然可以用矩阵树定理 \(\mathcal O(n^3 2^n)\) 解决。

但不妨直接计数,

\[f(S)=\frac{1}{2(|S|-1)}\sum_{T \subset S}f(T)f(S-T)E(T,S-T) \]

其中 \(E(S,T)\) 表示 \(S,T\) 之间的边数,令 \(E(S)\) 表示 \(S\) 内部的边数 ,有:

\[E(S,T)=E(S|T)-E(S)-E(T) \]

这部分可以 \(\mathcal O(3^n+n^22^n)\) 解决。

那么整个问题可以在 \(\mathcal O(2^nn^3+3^n)\) 内解决。

总结

大部分图计数都可以通过划分联通快形成子问题,从而求解。

#include <bits/stdc++.h>
using namespace std;
#define pc __builtin_popcount

const int MAXN = 14 , MAXM = 500 , Mod = 998244353;
inline int Add( int x , int y ) { x += y; return x >= Mod ? x - Mod : x; }
inline int Sub( int x , int y ) { x -= y; return x < 0 ? x + Mod : x; }
inline int Mul( int x , int y ) { return 1ll * x * y % Mod; }
inline int Qkpow( int x , int po ) { int p = 1; for( ; po ; po >>= 1 , x = Mul( x , x ) ) if( po & 1 ) p = Mul( p , x ); return p; }
inline int Inv( int x ) { return Qkpow( x , Mod - 2 ); }
int fac[ 105 ] , ivf[ 105 ] , iv[ 105 ];

void fwtor( int n , int *f , int op ) {
    for( int len = 2 ; len <= n ; len <<= 1 )
        for( int l = 0 ; l < n ; l += len )
            for( int i = l ; i < l + len / 2 ; i ++ )
                f[ i + len / 2 ] = Add( f[ i + len / 2 ] , op == 1 ? f[ i ] : Sub( 0 , f[ i ] ) );
}
int fs[ MAXN + 1 ][ 1 << MAXN ] , gs[ MAXN + 1 ][ 1 << MAXN ] , hs[ MAXN + 1 ][ 1 << MAXN ];
void fst( int n , int *f , int *g , int *h ) {
    for( int i = 0 ; i < 1 << n ; i ++ ) fs[ pc( i ) ][ i ] = f[ i ] , gs[ pc( i ) ][ i ] = g[ i ];
    for( int i = 0 ; i <= n ; i ++ ) fwtor( 1 << n , fs[ i ] , 1 ) , fwtor( 1 << n , gs[ i ] , 1 );
    for( int i = 0 ; i <= n ; i ++ )
        for( int j = 0 ; j <= n - i ; j ++ )
            for( int k = 0 ; k < 1 << n ; k ++ )
                hs[ i + j ][ k ] = Add( hs[ i + j ][ k ] , Mul( fs[ i ][ k ] , gs[ j ][ k ] ) );
    for( int i = 0 ; i <= n ; i ++ ) fwtor( 1 << n , hs[ i ] , -1 );
    for( int i = 0 ; i < 1 << n ; i ++ ) h[ i ] = hs[ pc( i ) ][ i ];
    for( int i = 0 ; i <= n ; i ++ ) for( int j = 0 ; j < 1 << n ; j ++ ) fs[ i ][ j ] = gs[ i ][ j ] = hs[ i ][ j ] = 0;
} 

int n , m , G[ MAXN ][ MAXN ] , E[ 1 << MAXN ];
int f[ 1 << MAXN ] , g[ MAXN + 1 ][ 1 << MAXN ];

inline int Ecnt( int S , int T ) { return E[ S | T ] - E[ S ] - E[ T ]; }
int main( ) {
    fac[ 0 ] = 1; ivf[ 0 ] = 1;
    for( int i = 1 ; i <= 100 ; i ++ ) {
        fac[ i ] = Mul( fac[ i - 1 ] , i );
        ivf[ i ] = Inv( fac[ i ] ); iv[ i ] = Inv( i );
    }

    scanf("%d %d",&n,&m);
    for( int i = 1 , u , v ; i <= m ; i ++ ) {
        scanf("%d %d",&u,&v); u -- , v --;
        G[ u ][ v ] ++; G[ v ][ u ] ++;
    }

    for( int S = 0 ; S < 1 << n ; S ++ ) {
        for( int i = 0 ; i < n ; i ++ ) if( ( S >> i ) & 1 )
            for( int j = i ; j < n ; j ++ ) if( ( S >> j ) & 1 )
                E[ S ] += G[ i ][ j ];
    }

    for( int S = 1 ; S < 1 << n ; S ++ ) {
        if( pc( S ) == 1 ) { f[ S ] = 1; continue; }
        for( int T = S ; T ; T = ( T - 1 ) & S )
            f[ S ] = Add( f[ S ] , Mul( Mul( f[ T ] , f[ S ^ T ] ) , Ecnt( T , S ^ T ) ) );
        f[ S ] = Mul( f[ S ] , iv[ 2 * ( pc( S ) - 1 ) ] );
    }

    g[ 0 ][ 0 ] = 1;
    for( int i = 1 ; i < n ; i ++ ) {
        // for( int S = 0 ; S < 1 << n ; S ++ ) {
        //     for( int T = S ; T ; T = ( T - 1 ) & S )
        //         g[ i ][ S ] = Add( g[ i ][ S ] , Mul( f[ T ] , g[ i - 1 ][ S ^ T ] ) );
        // }
        fst( n , f , g[ i - 1 ] , g[ i ] );
        for( int S = 0 ; S < 1 << n ; S ++ )
            g[ i ][ S ] = Mul( g[ i ][ S ] , iv[ i ] );
    }

    for( int i = 1 ; i < n ; i ++ )
        printf("%d\n", Mul( Mul( g[ n - i ][ ( 1 << n ) - 1 ] , fac[ i ] ) , Inv( Qkpow( m , i ) ) ) );
    return 0;
}

标签:inline,return,int,ABC253Ex,Forest,mathcal,Love,po,Mod
From: https://www.cnblogs.com/chihik/p/abc253_h.html

相关文章

  • 【C语言】用"I love you!"打印心形
    #include<iostream>#include<cmath>usingnamespacestd;intmain(){floatx,y;strings="Iloveyou!";intl=s.length();for(y=1.3f;......
  • 文件管理工具“三剑客” #Everything #SpaceSniffer #Clover
    前言:本文收集了我日常使用的三个文件管理工具:文件搜索神器——Everything磁盘文件占用分析工具——SpaceSniffer文件资源管理器——Clover下面我从工具解决的痛点......
  • 文件管理工具“三剑客” #Everything #SpaceSniffer #Clover
    前言:本文收集了我日常使用的三个文件管理工具:文件搜索神器——Everything磁盘文件占用分析工具——SpaceSniffer文件资源管理器——Clover下面我从工具解决的痛点和......
  • 10.5 George_Plover
    T1简单点简单点因为没看清楚题意,\(eeeaaasssyy\)实际只算一个分析从贪心的角度入手,每一个字符都匹配下一个必然最多对于每一个\(e\)找到最近的下一个\(a\)对于每......
  • 10.4 George_Plover
    题面T1一道数学(博弈论)分析先手搓几个数据,找找规律,除非个数为1,其余的一旦先手先选,那一定先手获胜,反之必败那只用统计1的个数即可,但如果全是1,需要特判#include<cstdi......
  • CF796A The Enchanted Forest
    有一条有n个点的数轴X,每个点有ai个蘑菇,小明可以从任意一点开始,每分钟他做以下操作:    1.往左移,往右移,或待在原地(从位置$x$移到位置$y$,$abs(x-y)<=1$)   ......
  • Lyk Love painting
    LykLovepainting一道超出常规的动态规划题干【题目描述】lyk有一块神奇的画布,呈2*n的格子状。lyk现在想在画布上画m幅画,每幅画必须是矩形。为了充分利用画布,画布上的......
  • Arc SQL MI: Multi-cloud Database failover using Distributed AG
    Reference:https://techcommunity.microsoft.com/t5/azure-architecture-blog/arc-sql-mi-demonstrating-multi-cloud-database-failover-using/ba-p/2936589architect......
  • 【题解】DZY Loves Math V
    题目描述给你\(n\)个整数\(a_i\)叫你求:\[\sum_{i_1|a_1}\sum_{i_2|a_2}\sum_{i_3|a_3}\cdots\sum_{i_n|a_n}\varphi(i_1i_2i_3\cdotsi_n)\]简要思路发现对于欧拉......
  • [极客大挑战 2019]LoveSQL 1
    很明显这时一道SQL注入的题目这题很简单的SQL注入题目,使用union(联合查询注入),但是缠了我很久为什么呢?因为我们学校的waf,很多可以注入成功的语句,他都会连接被重置,或者被b......