zoukankan      html  css  js  c++  java
  • codeforces315Div1 B Symmetric and Transitive

    http://codeforces.com/contest/568/problem/B

    题意就是给一个有n个元素的集合,现在需要求有多少个A的二元关系p,使得p是对称的,是传递的,但不是自反的。

    首先只用(x1, x1), (x2, x2).....这种二元对形成的传递,对称,非自反的满足条件的方法数为2^n - 1(每一对可以选择出现或者不出现,全部出现的情况是自反的,所以减掉1)

    其次,由于如果存在(a, b)a!=b的二元关系对,那么a,b这两个元素一定在某一个环中(根据对称一定有(b, a)又根据传递一定有(a, a)与(b, b)),那么答案就是求不是每个点都在某一个环中的方法数,那么这时把某一个环看成是一个集合。设G[i]表示i个点形成若干个集合的方法数,再令F[i][j]表示i个点形成j个集合的方法数,那么G[i] = sigma(F[i][j] | j <= i/2),下面计算F[i][j]:

          F[i][j] = F[i - 1][j] * j + F[i - 2][j - 1] * (i - 1)

    就是指第i个元素可以放在之前的某一个集合中,也可以与之前的某一个元素形成个数为2的集合

    在算出G[i]后,来统计答案,这时候需要枚举有多少个(x, x)这样的二元对,设为i个,那么剩下的点就有n-i个,剩下的点可以选择j个(2 <= j <= n - i)来形成若干个集合来与i个(x, x)的数对形成一个合法的答案。那么这里合法的大案数量就是

          sigma(C[n][i] * sigma(C[n - i][j] * G[j]))其中,1<=i<=n-2  2<=j<=n-i   C为组合数

     

    #include <map>
    #include <set>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <ctime>
    #include <vector>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define inf (-((LL)1<<40))
    #define lson k<<1, L, mid
    #define rson k<<1|1, mid+1, R
    #define mem0(a) memset(a,0,sizeof(a))
    #define mem1(a) memset(a,-1,sizeof(a))
    #define mem(a, b) memset(a, b, sizeof(a))
    #define FIN freopen("in.txt", "r", stdin)
    #define FOUT freopen("out.txt", "w", stdout)
    #define rep(i, a, b) for(int i = a; i <= b; i ++)
    #define dec(i, a, b) for(int i = a; i >= b; i --)
    
    //typedef __int64 LL;
    typedef long long LL;
    const int MAXN = 4002;
    const int MAXM = 110000;
    const double eps = 1e-12;
    const double PI = 4.0 * atan(1.0);
    const int MOD = 1000000007;
    
    LL F[MAXN], C[MAXN][MAXN];
    
    void initF(int n) {
        F[2] = C[2][1] = 1;
        rep (i, 3, n) {
            F[i] = C[i][1] = 1;
            rep (j, 2, i / 2) {//C[i][j]表示i个点形成j个集合(环)的方案数
                C[i][j] = ( C[i - 1][j] * j % MOD + (i - 1) * C[i - 2][j - 1] % MOD ) % MOD;
                F[i] = ( F[i] + C[i][j] ) % MOD; //F[i]表示i个点形成若干个集合(环)的方案数
            }
        }
    }
    
    void initC(int n) {
        mem0(C);
        C[0][0] = 1;
        rep (i, 1, n) {
            C[i][0] = C[i][i] = 1;
            rep (j, 1, n - 1) //C[i][j]为组合数
                C[i][j] = ( C[i - 1][j - 1] + C[i - 1][j] ) % MOD;
        }
    }
    
    
    int main()
    {
    #ifndef ONLINE_JUDGE
        FIN;
    //    FOUT;
    #endif // ONLINE_JUDGE
        initF(4001);
        initC(4001);
        int n;
        while(cin >> n) {
            LL ans = 1;
            //首先计算2^n - 1
            rep (i, 1, n) ans = ans * 2 % MOD;
            ans = (ans - 1 + MOD) % MOD;
    
            //sigma(C[n][i] * sigma(C[n - i][j] * G[j]))
            rep (i, 1, n - 2) {
                int m = n - i;
                LL S = 0;
                rep (j, 2, m) {
                    S = ( S + C[m][j] * F[j] ) % MOD;
                }
                ans = (ans + S * C[n][i]) % MOD;
            }
            cout << ans << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    大数据HIve
    大数据笔记
    [Leetcode]653.Two Sum IV
    [Leetcode]652.Find Duplicate Subtrees
    [Leetcode]650.2 Keys Keyboard
    [Leetcode]648.Replace Words
    [Leetcode Weekly Contest]173
    [总结]最短路径算法
    [Leetcode]647.Palindromic Substrings
    [Leetcode]646.Maximum Length of Pair Chain
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/4738190.html
Copyright © 2011-2022 走看看