当前位置: 首页 > news >正文

「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

相关文章:

  • Object 类有哪些方法
  • 为了使用好Apache Flink,Yelp实现了一个连接算法
  • C++多态
  • MariaDB 数据库
  • 应用调试(三)oops
  • 谷歌是 CNCF 开源项目最大贡献者,红帽次之
  • 海南“多规合一”改革促行政审批提速城乡面貌提质
  • jmap命令 Java Memory Map
  • 服务器从安装到部署全过程(二)
  • 对APP单例的统一封装(常规式)
  • 优化关键渲染路径
  • TiDB 3.0 Beta Release Notes
  • 台湾屏东县一肉鸭场检验出禽流感 扑杀6510只肉鸭
  • 山西球迷大范围辱骂裁判被CBA公司罚款2万元
  • 从前后端分离到GraphQL,携程如何用Node实现?\n
  • .pyc 想到的一些问题
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • C++类的相互关联
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Linux Process Manage
  • Mysql5.6主从复制
  • Sass 快速入门教程
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • vue 配置sass、scss全局变量
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • vue总结
  • Wamp集成环境 添加PHP的新版本
  • XML已死 ?
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 基于webpack 的 vue 多页架构
  • 今年的LC3大会没了?
  • 坑!为什么View.startAnimation不起作用?
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 小程序测试方案初探
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • #Linux(make工具和makefile文件以及makefile语法)
  • #宝哥教你#查看jquery绑定的事件函数
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (04)odoo视图操作
  • (16)Reactor的测试——响应式Spring的道法术器
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (ZT)薛涌:谈贫说富
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (算法)Game
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (转)重识new
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .equals()到底是什么意思?
  • .Net - 类的介绍
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .NET Core WebAPI中封装Swagger配置
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NET Core中Emit的使用
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON