codeforces 568B B. Symmetric and Transitive(贝尔数+组合数学)

题目链接:

codeforces

题目大意:

给出n,代表集合元素个数,求出满足传递性和对称性但不满足自反性的集合的数目。

题目分析:

我们可以将这个集合看作一个无向图,也就是对于每个联通块当中的点都是满足这三个性质的。所以所有不符合要求的就是我们选取图中的一些点(但不能是全部的点),然后对他们进行划分,也就是集合的划分的数目。(划分出的每个集合是一个联通块),而集合的划分数目正好就是贝尔数。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 4007

using namespace std;
typedef long long LL;

int n;

LL c[MAX][MAX];
LL b[MAX][MAX];
const LL mod = 1e9+7;

void init ( )
{
    c[0][0] = c[1][0] = c[1][1] = 1;
    for ( int i = 2 ; i < MAX ; i++ )
        for ( int j = 0 ; j <= i ; j++ )
            if ( j == 0 || j == i ) c[i][j] = 1;
            else
            {
                c[i][j] = c[i-1][j] + c[i-1][j-1];
                c[i][j] %= mod;
            }
    b[0][0] = b[1][1] = 1;
    for ( int i = 2 ; i < MAX ; i++ )
    {
        b[i][1] = b[i-1][i-1];
        for ( int j = 2 ; j <= i ; j++ )
        {
            b[i][j] = b[i][j-1] + b[i-1][j-1];
            b[i][j] %= mod;
        }
    }
}

int main ( )
{
    init ( );
    while ( ~scanf ( "%d" , &n ) )
    {
        LL ans = 0;
        for ( int i = 0 ; i < n ; i++ )
        {
            ans += c[n][i]*b[i][i]%mod;
            ans %= mod;
        }
        printf ("%I64d\n" , ans );
    }
}

你可能感兴趣的:(codeforces,组合数学,贝尔数)