zoukankan      html  css  js  c++  java
  • CF340E Iahub and Permutations

    (洛谷)题目链接

    Solution

    统计所有可能的放法,减去不合法情况。

    设一共有 (num) 个位置缺失,其中有 (q) 个位置可能不合法。

    枚举 (i) ((1≤i≤q)),表示当前有 (i) 个位置不合法。则有 (C(i,q)) 种取法,剩下的数有 ((num-i)!) 种排列方式。注意在组合数时除法要用乘法逆元来代替。

    得到公式:(ans+=(-1)^i*C(i,q)*(num-i)!) ((1≤i≤q))

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define LL long long
    using namespace std;
     
    const int N = 2333, mod = 1e9 + 7;
    LL n, ans, q = 0, num = 0, a[N], f[N], inv[N], vis[N];
     
    LL poww(LL b, LL p)
    {
        LL res = 1;
        while(p)
        {
            if(p & 1) res = (res * b) % mod;
            b = (b * b) % mod;
            p >>= 1;
        }
        return res % mod;
    }
    LL C(LL x, LL y) { return ((f[x] * inv[y]) % mod * inv[x - y]) % mod; }
     
    int main()
    {
        scanf("%lld", &n);
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld", &a[i]);
            if(a[i] == -1) num++;
            else vis[a[i]] = 1;
        }
        for(int i = 1; i <= n; i++)
            if(a[i] == -1 && vis[i] == 0) q++;
        f[0] = 1;
        for(int i = 1; i <= n; i++)
            f[i] = (f[i - 1] * i) % mod;
        inv[n] = poww(f[n], mod - 2);
        for(int i = n - 1; i >= 1; i--)
            inv[i] = inv[i + 1] * (i + 1) % mod;
        inv[0] = 1;
        ans = f[num];
        for(int i = 1; i <= q; i++)
            ans = (ans + ((poww(-1, i & 1) * C(q, i)) % mod * f[num - i]) % mod) % mod;
        while(ans < 0) ans += mod;
        printf("%lld", ans % mod);
        return 0;
    }
    
  • 相关阅读:
    HDU1260DP
    HDU1114 背包
    HDU1078记忆化搜索
    HDU1024 最大m子段和
    Codeforces Round #401 (Div. 2) A,B,C,D,E
    HDU3666 差分约束
    HDU1540 区间合并
    HDU3308 线段树(区间合并)
    Codeforces Round #403 (Div. 2) B 三分 C dfs
    HDU1573 线性同余方程(解的个数)
  • 原文地址:https://www.cnblogs.com/Andy-park/p/13432191.html
Copyright © 2011-2022 走看看