Min-Max容斥

Min-Max容斥

公式:

应用:

常用来求“每次选一个数,使每个数被选的次数至少到达某个值的期望次数”

首先我们要知道对于一个局面(比如第一个数选1次,第二个数选2次)的期望步数就是这个局面的概率分之一

证明:设期望为,概率为,那么,化简得

普遍情况:

个数,每个数有个权重,那么每一次选中第个数的概率就为,问每个数被选的次数至少到达的期望次数。

公式:

解释:

是得到一个指定集合内元素的期望时间,有重复元素的排列下,是对于集合内每个数的概率。
这个式子是怎么推出来的呢?
可以发现答案可以转化为每种状态的持续期望时间之和。那么就是状态改变的期望时间,就是每一种状态出现的概率。

例题:

E - Gachapon

题意:

个数,每个数有个权重,那么每一次选中第个数的概率就为,问每个数被选的次数至少到达的期望次数。

题解:

暴力做法就是枚举集合,然后通过上面给出的式子进行计算。

正解,考虑已经求出了一个集合的答案,现在要在这个集合里加入一个新的数

发现只要记录一下即可转移

代码:

#include<bits/stdc++.h>
using namespace std;
#define next Next
#define gc getchar
#define int long long
const int N=405;
const int mod=998244353;
int n,a[N],b[N],jc[N],inv[N],sum[N],f[N][N][N];
/*char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}*/
inline int read()
{
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}
int kuai(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b=b/2;
    }
    return res;
}
signed main()
{
    n=read();
    for(int i=1;i<=n;i++)a[i]=read(),b[i]=read();
    jc[0]=jc[1]=inv[0]=inv[1]=1;
    for(int i=2;i<=400;i++)jc[i]=jc[i-1]*i%mod;
    for(int i=2;i<=400;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    for(int i=2;i<=400;i++)inv[i]=inv[i]*inv[i-1]%mod;
    int s1=0,s2=0;
    f[0][0][0]=mod-1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=s1;j++)
            for(int k=0;k<=s2;k++)
                f[i][j][k]=f[i-1][j][k];
        sum[0]=1;
        for(int j=1;j<b[i];j++)sum[j]=sum[j-1]*a[i]%mod;
        for(int j=0;j<b[i];j++)sum[j]=sum[j]*inv[j]%mod;
        for(int j=0;j<=s1;j++)
            for(int k=0;k<=s2;k++)
                for(int p=0;p<b[i];p++)
                    f[i][j+p][k+a[i]]=(f[i][j+p][k+a[i]]-f[i-1][j][k]*sum[p]%mod+mod)%mod;
        s1+=b[i]-1;s2+=a[i];
    }
    int ans=0;
    for(int i=0;i<=s1;i++)
        for(int j=1;j<=s2;j++)
        {
            int x=f[n][i][j]*jc[i]%mod;
            x=x*kuai(kuai(j,mod-2),i)%mod;
            ans=(ans+x*s2%mod*kuai(j,mod-2)%mod)%mod;
        }
    cout<<ans;
}
xuxuxuxuxu 文章被收录于专栏

信息学竞赛

全部评论
%%%
点赞 回复 分享
发布于 2020-09-05 00:09

相关推荐

06-26 18:30
门头沟学院 Java
据说名字越长别人越关注你的昵称我觉得我要被关注了:你问问这里面有多少是正经候选人,而不是乱打招呼的
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
06-26 15:18
点赞 评论 收藏
分享
白火同学:大二有这水平很牛了,可以适当对关键信息加粗一点,比如关键技术、性能指标之类的。
点赞 评论 收藏
分享
家人们,我现在真的好纠结。我是26届的,目前还没有实习过。我现在的情况是,想参加秋招,但是感觉自己的简历特别空,没有实习经历会不会秋招直接凉凉啊?可我又听说现在很多公司对26届实习生也不太感冒,说什么不确定性大。而且我最近在准备考公,时间上也有点冲突。要是把时间花在实习上,备考时间就少了。但要是不实习,又怕以后就业有问题😫有没有懂行的友友帮我分析分析:26届现在不实习,秋招找工作真的会很难吗?考公和实习该怎么平衡啊?如果现在不实习,考完公再去找实习还来得及吗?真的太焦虑了,希望大家能给我点建议🙏
小破站_程序员YT:我可能和大家的观点不一样。人的精力是有限的,不能既要还要。你又想实习又想考公最后又要秋招上岸,我觉得哪有那么多的选择。你如果想考上岸,那就全力以赴。如果想秋招上岸,就继续投实习,投没了,就继续准备秋招,秋招不行继续春招。别到最后,考公没上岸,觉得是花了时间浪费在找实习上了, 秋招没上岸,觉得是浪费时间准备考公去了。我是认为很难说可以去平衡 不喜勿喷,可以叫我删除
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务