• CCA的小球【容斥定理】


    题意

    给定 (n) 个小球,每个小球有颜色,要将它们摆成一行 。两个方案不同,当且仅当存在某个位置,两种方案摆在这个位置的小球颜色不同。一个方案合法,当且仅当不存在任意两个位置相邻的小球颜色相同,求合法方案数对 (10^9+7) 取模后的值。((nleq 10^6)),每种颜色出现的次数 (leq 2)
    链接:https://ac.nowcoder.com/acm/contest/11168/D

    分析

    发现合法方案不好求解。因此,可以求出不合法的方案的数量,从总方案中减去即为合法方案数。在计算不合法方案数时,对相邻同色球的对数进行讨论。会发现出现重复,采用容斥定理来去重。计算是注意可重集合的排列数计算。代码实现时,一开始使用离散化的方式,但一直错。换成直接排序判断相邻是否相同就过了。

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    const int mod=1e9+7;
    const int N=1e6+6;
    int a[N],fac[N],inv[N],num[N];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        fac[0]=1,inv[1]=1;
        for(int i=1;i<=n;i++) fac[i]=1LL*fac[i-1]*i%mod;
        for(int i=2;i<=n;i++) inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
        sort(a+1,a+1+n);
        int ans=0,m=0,pw=1,res=1;
        for(int i=2;i<=n;i++)
            if(a[i]==a[i-1]) m++;
        for(int i=1;i<=m;i++) pw=1LL*pw*inv[2]%mod;
        ans=1LL*fac[n]*pw%mod;
        for(int i=1;i<=m;i++)
        {
            res=1LL*res*(m-i+1)%mod;
            res=1LL*res*inv[i]%mod;
            pw=2LL*pw%mod;
            if(i&1) ans=(ans-1LL*res*fac[n-i]%mod*pw%mod)%mod;
            else ans=(ans+1LL*res*fac[n-i]%mod*pw%mod)%mod;
            ans=(ans+mod)%mod;
        }
        printf("%d
    ",(ans+mod)%mod);
        return 0;
    }
    
    
  • 相关阅读:
    转载的一篇嵌入式大佬经验博文
    工程训练大赛心得体会
    Python之闭包与延时绑定问题
    python基础之装饰器
    python之内置函数(map,fillter,reduce)
    *arg和**kwarg作用
    C++之 ostream详细用法
    Linux 常用命令
    C++ 人脸识别系统的浅理解
    Linux 应用领域
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/14536087.html
Copyright © 2020-2023  润新知