zoukankan      html  css  js  c++  java
  • 「HNOI2008」明明的烦恼

    传送门

    这题的弱化版

    (prufer) 序列题。

    我们先考虑度数确定的点,记度数确定的点有 (k) 个,它们在 (prufer) 序列中一共出现 (cnt) 次。

    首先我们要从 (prufer) 序列的 (n - 2) 个位置中选 (cnt) 个来放这些点,然后我们考虑
    先不确定其它 (n - k) 个点的位置,此时方案数为:({n - 2 choose cnt}frac{cnt!}{prod_{d_i e-1} {(d_i - 1)!}})

    那么剩下 (n - k) 个点怎么处理呢?我们考虑把他们直接塞到剩下 (n - 2 - cnt) 个空中去就好了 (Q omega Q) ,方案数就是一个乘法原理:((n - k) ^ {n - 2 - cnt})

    最后的答案就是 ({n - 2 choose cnt}frac{cnt!}{prod_{d_i e-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt})

    稍微化简一下:

    [egin{aligned} ans & = {n - 2 choose cnt}frac{cnt!}{prod_{d_i e-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt} \ & = frac{(n - 2)!}{cnt! imes (n - 2 - cnt)!} imes frac{cnt!}{prod_{d_i e-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt} \ & = frac{(n - 2)!}{(n - 2 - cnt)! imes prod_{d_i e-1} {(d_i - 1)!}}(n - k) ^ {n - 2 - cnt} end{aligned} ]

    然后写个高精直接求就是了

    参考代码:

    #include <cstdio>
    #include <vector>
    using namespace std;
    
    const int _ = 1e3 + 5;
    
    struct BigInteger {
        vector < int > s;
        BigInteger() { s.clear(); }
        BigInteger clean() { while (s.size() && !s.back()) s.pop_back(); return *this; }
        BigInteger operator = (int x) {
            s.clear();
            while (x) s.push_back(x % 10), x /= 10;
            return this -> clean();
        }
        BigInteger operator * (const int& x) {
            int g = 0;
            for (int i = 0; i < s.size(); ++i) s[i] *= x;
            for (int i = 0; i < s.size(); ++i)
                s[i] += g, g = s[i] / 10, s[i] %= 10;
            while (g) s.push_back(g % 10), g /= 10;
            return this -> clean();
        }
        BigInteger operator / (const int& x) {
            int g = 0;
            for (int i = s.size() - 1; i >= 0; --i) {
                g = g * 10 + s[i];
                if (g >= x) s[i] = g / x, g %= x; else s[i] = 0;
            }
            return this -> clean();
        }
        void output() { for (int i = s.size() - 1; i >= 0; --i) printf("%d", s[i]); puts(""); }
    } ans;
    
    int n, k, s, d[_];
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("cpp.in", "r", stdin), freopen("cpp.out", "w", stdout);
    #endif
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", d + i);
        if (n == 1) { puts(d[1] == -1 || d[1] == 0 ? "1" : "0"); return 0; }
        for (int i = 1; i <= n; ++i) if (d[i] != -1) ++k, s += d[i] - 1;
        if (s > n - 2) { puts("0"); return 0; }
        ans = 1;
        for (int i = 1; i <= n - 2; ++i) ans = ans * i;
        for (int i = 1; i <= n - 2 - s; ++i) ans = ans * (n - k);
        for (int i = 1; i <= n - 2 - s; ++i) ans = ans / i;
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= d[i] - 1; ++j) ans = ans / j;
        ans.output();
        return 0;
    }
    
  • 相关阅读:
    windows 按时自动化任务
    Linux libusb 安装及简单使用
    Linux 交换eth0和eth1
    I.MX6 GPS JNI HAL register init hacking
    I.MX6 Android mmm convenient to use
    I.MX6 GPS Android HAL Framework 调试
    Android GPS GPSBasics project hacking
    Python windows serial
    【JAVA】别特注意,POI中getLastRowNum() 和getLastCellNum()的区别
    freemarker跳出循环
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/13096509.html
Copyright © 2011-2022 走看看