zoukankan      html  css  js  c++  java
  • [BZOJ4665] 小w的喜糖

    [BZOJ4665] 小w的喜糖

    题目链接

    https://www.lydsy.com/JudgeOnline/problem.php?id=4665

    Solution

    考虑容斥,我们先认为同色的糖是本质不同的,不然容斥就不对,那么我们需要算出至少(k)个人糖果种类不变的方案数。

    (f_{i,j})表示前(i)种糖一共有至少(j)个人不变,直接暴力转移:

    [f_{i,j}=sum_{k=0}^{cnt_i}f_{i-1,j-k}inom{cnt_i}{k}cnt_i^{underline{k}} ]

    (k)是枚举当前糖不变的人数,我们先选出(k)个位置拿走,在任意地放回来,由于我们硬点了本质不同所以这玩意是对的。

    由于原题中同色本质相同,所以每种情况都被算了(prod cnt_i!),答案除掉就好了。

    复杂度很好证明,我们的总枚举次数大概是:

    [sum_{i=1}^{n}ncdot cnt_i =O(n^2) ]

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    
    #define pii pair<int,int >
    #define vec vector<int >
    
    #define pb push_back
    #define mp make_pair
    #define fr first
    #define sc second
    
    #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 
    
    const int maxn = 2010;
    const int inf = 1e9;
    const lf eps = 1e-8;
    const int mod = 1e9+9;
    
    int f[maxn][maxn],t[maxn],n,fac[maxn],ifac[maxn],inv[maxn],s[maxn];
    
    void prepare() {
        fac[0]=ifac[0]=inv[0]=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;
        for(int i=1;i<=n;i++) ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
    }
    
    int cmp(int x,int y) {return x>y;}
    
    int c(int x,int y) {return 1ll*fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
    
    int main() {
        read(n);for(int i=1,x;i<=n;i++) read(x),t[x]++;
        prepare();sort(t+1,t+n+1,cmp);int cnt=0;
        for(int i=1;i<=n+1;i++) if(!t[i]) {cnt=i-1;break;}
        f[0][0]=1;
        for(int i=1;i<=cnt;i++) s[i]=s[i-1]+t[i];
        for(int i=1;i<=cnt;i++)
            for(int j=0;j<=s[i];j++)
                for(int k=0;k<=j&&k<=t[i];k++) 
                    f[i][j]=(f[i][j]+1ll*f[i-1][j-k]*c(t[i],k)%mod*fac[t[i]]%mod*ifac[t[i]-k]%mod)%mod;
        int ans=0;
        for(int i=0,p=1;i<=n;i++,p=-p) ans=(ans+1ll*fac[n-i]*p*f[cnt][i]%mod)%mod;
        for(int i=1;i<=cnt;i++) ans=1ll*ans*ifac[t[i]]%mod;
        write((ans+mod)%mod);
        return 0;
    }
    
  • 相关阅读:
    C 获取编译日期函数
    C# HttpWebRequest 使用,一个Http分析Demo
    C# 字节序调整
    char/wchar_t之间的互转MultiByteToWideChar和WideCharToMultiByte的用法
    前导声明代替头文件依赖和交叉包含
    MFC network address control使用
    [收藏]POSIX标准
    带引用计数的智能指针
    C# string byte[] 转换
    DIV随鼠标滚动
  • 原文地址:https://www.cnblogs.com/hbyer/p/11054776.html
Copyright © 2011-2022 走看看