「PKUWC2018」猎人杀

传送门

Description

猎人杀是一款风靡一时的游戏“狼人杀”的民间版本,他的规则是这样的:

一开始有 \(n\)个猎人,第 \(i\) 个猎人有仇恨度 \(w_i\) ,每个猎人只有一个固定的技能:死亡后必须开一枪,且被射中的人也会死亡。

然而向谁开枪也是有讲究的,假设当前还活着的猎人有 \([i_1\ldots i_m]\),那么有 \(\frac{w_{i_k}}{\sum\limits_{j = 1}^{m}w_{i_j}}\) 的概率是向猎人 \(i_k\)开枪。

一开始第一枪由你打响,目标的选择方法和猎人一样(即有 \(\frac{w_i}{\sum\limits_{j=1}^{n}w_j}\) 的概率射中第\(i\) 个猎人)。由于开枪导致的连锁反应,所有猎人最终都会死亡,现在 \(1\) 号猎人想知道它是最后一个死的的概率。

答案对 \(998244353\)取模。

Solution

我们发现,在求概率的过程中,每一步的分母都是不一样的,这特别难受。

我们假设分母始终都是\(\sum_{j=1}^{n}w_j\),每次选一个猎人,如果这个猎人已经选过,就不变,继续选下一个,这样,每次新选中一个猎人的概率应该是与题目中一样的。

考虑容斥,令\(A=\)所有猎人的仇恨值之和

我们设在第一个猎人之后被射中的猎人集合包含集合\(X\),注意,是包含\(X\),而不是等于\(X\)\(X\)内元素的仇恨值之和是\(S\),那么这种情况出现的概率应为:
\[ P(X)=\sum_{i=0}^{\infty }(1-\frac{S+w_1}{A})^i\frac{w_1}{A} \]
然后,根据一个结论:
\[ \sum_{i=0}^{\infty}a^i=\frac{1}{1-a},其中满足0\leq a\leq 1 \]
所以,我们最终得到:
\[ P(X)=\frac{w_1}{S+w_1} \]
最后,根据容斥:
\[ ans=\sum_{X} (-1)^{|X|}P(X) \]
还是很难求,我们考虑计算对于一个\(S\)\(ans\)\(\frac{w_1}{S+w_1}\)的系数,因为题目给出\(S\leq10^5\),所以求出每一项的系数后直接相乘相加即可。


\[ S的系数=\sum_{X}[Sum(x)==S](-1)^{|X|} \]
我们考虑分治,假设已经求出\([l,mid]\)\([mid+1,r]\)的对于每个\(S\)的系数\({a_i}\)\(b_i\),显然,
\[ S的系数=\sum_{i=0}^{S}a_ib_{S-i} \]
直接用\(NTT\) 求卷积即可。

这样,总复杂度应为\(O(A\log^2A)\)


Code 

//2019.1.16 10:00~11:45 PaperCloud 
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define MN 100005
#define mod 998244353
#define g 3
#define invg 332748118
#define MM 262144
int t[30][MM],pos[MM],N,di,invN;
inline int fpow(int x,int m){int r=1;for(;m;x=1ll*x*x%mod,m>>=1)if(m&1)r=1ll*r*x%mod;return r;}
inline void NTT(int *a,int type)
{
    register int i,j,p,k,wn,w,X,Y;
    for(i=0;i<N;++i) if(i<pos[i]) std::swap(a[i],a[pos[i]]);
    for(i=1;i<N;i<<=1)
    {
        wn=fpow(type>0?g:invg,(mod-1)/(i<<1));
        for(p=i<<1,j=0;j<N;j+=p)
            for(w=1,k=0;k<i;++k,w=1ll*w*wn%mod)
            {
                X=a[j+k];Y=1ll*a[i+j+k]*w%mod;
                a[j+k]=(X+Y)%mod;a[i+j+k]=(X-Y+mod)%mod;
            }
    }
    if(type==-1) for(i=0;i<N;++i) a[i]=1ll*invN*a[i]%mod; 
}
int n,A=0,ans=0,top=0,P[30],w[MN];
#define last top-1
inline void solve(int l,int r)
{
    register int i;
    if(l==r)
    {
        P[++top]=w[l];t[top][0]=1;t[top][w[l]]=mod-1;
        for(i=1;i<w[l];++i) t[top][i]=0;return;
    }
    register int mid=(l+r)>>1;solve(l,mid);solve(mid+1,r);
    for(N=1,di=0;N<=P[top]+P[last];N<<=1,++di);invN=fpow(N,mod-2);
    for(i=0;i<N;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(di-1));
    for(i=P[last]+1;i<N;++i) t[last][i]=0;
    for(i=P[top]+1;i<N;++i) t[top][i]=0;
    NTT(t[last],1);NTT(t[top],1);for(i=0;i<N;++i) t[last][i]=1ll*t[last][i]*t[top][i]%mod;
    NTT(t[last],-1);P[last]=P[last]+P[top];top--;
}
int main()
{
    n=read();register int i;
    for(i=1;i<=n;++i) w[i]=read(),A+=w[i];A-=w[1];solve(2,n);
    for(i=0;i<=A;++i) (ans+=(1ll*w[1]*t[1][i]%mod*fpow(i+w[1],mod-2))%mod)%=mod;
    return 0*printf("%d\n",(ans+mod)%mod);
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

转载于:https://www.cnblogs.com/PaperCloud/p/10276474.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值