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

CF1096E.The Top Scorer[概率期望]

\[\text{题意:有}n\text{个人,每人有一个分数}a_i\left( a_i\geq 0 \right) ,\sum{a_i}=s\]
\[\text{假设最高分有}x\text{个,}x\text{个人中的每个人都有}\frac{1}{x}\text{的概率获胜}\]
\[\text{第1个人的得分一定在}\left[ r,s \right] \text{之内,给出}n,s,r\text{,求他的获胜概率}\]
\[\text{用隔板法,有}\left( \begin{array}{c} s-r+n-1\\ n-1\\ \end{array} \right)\text{种方案}\left( \text{有}r\text{个球已经被固定分给第1个人了} \right)\]
\[\text{求出第1个人作为最高分有多少种方案,再除以总方案数就是获胜概率(要除以同分人数)}\]
\[\text{枚举第1个人得了多少分}x\text{,以及跟他同分的人的个数}y\text{(不包括自己)}\]
\[\text{令}f\left( a,b,c \right) \text{表示}a\text{个非负整数的和是}b,\text{这}a\text{个数的上界是}c\text{的方案数}\]
\[\text{不考虑上界答案是}\left( \begin{array}{c} b+a-1\\ a-1\\ \end{array} \right) \text{(隔板法)}\]

\[g\left( i \right) \text{表示}\geq n-i\text{个不合法}\left( \leq i\text{个合法} \right) \text{的方案数,}h\left( i \right) \text{表示有}n-i\text{个不合法}\left( i\text{个合法} \right) \text{的方案数,}\]
\[g\left( x \right) =\sum_{i=0}^x{\left( \begin{array}{c} n\\ i\\ \end{array} \right) h\left( i \right)}\]
\[\text{要求}h\left( n \right) ,\text{由二项式反演}\]
\[h\left( n \right) =\sum_{i=0}^n{\left( -1 \right) ^{n-i}\left( \begin{array}{c} n\\ i\\ \end{array} \right) g\left( i \right)}\]

\[\text{对于一个}x\text{,}\sum_{y=0}^{n-1}{\left( \begin{array}{c} n-1\\ y\\ \end{array} \right) f\left( n-y-1,s-x\left( y+1 \right) ,x-1 \right)}\text{就是}x\text{作为最高分的方案数}\]

\[\text{所以答案就是}\frac{\sum_{x=r}^s{\begin{array}{c} \sum_{y=0}^{n-1}{\frac{\left( \begin{array}{c} n-1\\ y\\ \end{array} \right) f\left( n-y-1,s-x\left( y+1 \right) ,x-1 \right)}{\left( y+1 \right)}}\\ \end{array}}}{\left( \begin{array}{c} s-r+n-1\\ n-1\\ \end{array} \right)}\]

#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
inline int Pow(int x, int y) {
  int ret;
  for (ret = 1; y; y >>= 1, x = x * 1ll * x % mod) if (y & 1) ret = ret * 1ll * x % mod;
  return ret % mod;
}
struct Moder {
  int a;
  Moder(int a) : a(a) {}
  Moder() {}
  inline int inv() {return Pow(a, mod - 2);}
  inline void operator += (const int b) {a += b; if (a < 0) a += mod; else if (a >= mod) a -= mod;}
  inline void operator -= (const int b) {a -= b; if (a < 0) a += mod; else if (a >= mod) a -= mod;}
  inline void operator *= (const int b) {a = a * 1ll * b % mod; if (a < 0) a += mod;}
  inline void operator /= (const int b) {a = a * 1ll * Pow(b, mod - 2) % mod; if (a < 0) a += mod;}
  inline void operator += (const Moder &rhs) {*this += rhs.a;}
  inline void operator -= (const Moder &rhs) {*this -= rhs.a;}
  inline void operator *= (const Moder &rhs) {*this *= rhs.a;}
  inline void operator /= (const Moder &rhs) {*this /= rhs.a;}
  inline Moder operator + (const Moder &rhs) const {Moder c = *this; c += rhs; return c;}
  inline Moder operator - (const Moder &rhs) const {Moder c = *this; c -= rhs; return c;}
  inline Moder operator * (const Moder &rhs) const {Moder c = *this; c *= rhs; return c;}
  inline Moder operator / (const Moder &rhs) const {Moder c = *this; c /= rhs; return c;}
  inline void operator = (const int x) {a = x;}
  inline void operator = (const Moder &rhs) {a = rhs.a;}
} fac[10005], ifac[10005];
int n, s, r;
inline Moder C(int n, int m) {
  if (m > n || m < 0) return 0;
  return fac[n] * ifac[n - m] * ifac[m];
}
inline Moder F(int n, int m) {//n个非负整数的和是m的方案数
  if (m < 0) return 0;
  return C(n + m - 1, n - 1);
}

inline Moder F1(int n, int m, int r) { //n个非负整数的和是m 上界是r的方案数
  if (!n && !m) return Moder(1); //这里是合法的,需要return 1
  Moder ret = 0, sign = (n & 1) ? -1 : 1;
  for (int i = 0; i <= n; ++i, sign = sign * -1) if (m - (r + 1) * (n - i) >= 0) ret = ret + sign * C(n, i) * F(n, m - (r + 1) * (n - i));
  // Moder ret = 0, sign = 1;
  // for (int i = 0; i <= n && m - (r + 1) * i >= 0; ++i, sign = sign * -1) ret = ret + sign * C(n, i) * F(n, m - (r + 1) * i);
  //容斥
  return ret;
}

int main() {
  fac[0] = 1;
  for (int i = 1; i <= 5100; ++i) fac[i] = fac[i - 1] * i;
  ifac[5100] = fac[5100].inv();
  for (int i = 5099; i >= 0; --i) ifac[i] = ifac[i + 1] * (i + 1);
  cin >> n >> s >> r;
  Moder ans = 0;
  for (int x = r; x <= s; ++x) {
    for (int y = 0; (y + 1) * x <= s && y + 1 <= n; ++y) {
      int m = n - y - 1, ss = s - (y + 1) * x;
      ans += F1(m, ss, x - 1) * C(n - 1, y) / (y + 1);
    }
  }
  ans /= C(s - r + n - 1, n - 1);
  cout << ans.a;
  return 0;
}

转载于:https://www.cnblogs.com/storz/p/10229458.html

相关文章:

  • 老司机 iOS 周报 #51 | 2019-01-07
  • 华为重磅发布芯片,领衔开启2019 CES,一文看尽五大硬核亮点
  • Sping boot和mybatis整合
  • PDF编辑软件怎么编辑PDF里的文字
  • 杭电2057
  • High Quality GPU FSAA Rasteration
  • 什么是DVD?DVD有些格式?
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • learn C++ or C# Options
  • Linux系统中/dev/mtd与/dev/mtdblock的区别
  • Linux设备驱动程序工作原理
  • sql 行转列的终极写法
  • 感觉这个JQuery不错,查询方便
  • Delphi2010 API延迟加载
  • 移动客户端搜索速度优化 —— 手机百度“云和端技术实践”沙龙
  • 《深入 React 技术栈》
  • git 常用命令
  • Go 语言编译器的 //go: 详解
  • input实现文字超出省略号功能
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Javascript Math对象和Date对象常用方法详解
  • JavaScript-Array类型
  • LeetCode算法系列_0891_子序列宽度之和
  • MaxCompute访问TableStore(OTS) 数据
  • 测试开发系类之接口自动化测试
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 关于springcloud Gateway中的限流
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 怎么把视频里的音乐提取出来
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • 如何在招聘中考核.NET架构师
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (译)2019年前端性能优化清单 — 下篇
  • (转)Linux整合apache和tomcat构建Web服务器
  • .net core webapi 大文件上传到wwwroot文件夹
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET 中创建支持集合初始化器的类型
  • .NET 中的轻量级线程安全
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .net操作Excel出错解决
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • [.net]官方水晶报表的使用以演示下载
  • [C++]拼图游戏
  • [C++进阶篇]STL中vector的使用
  • [ffmpeg] 定制滤波器
  • [GN] 后端接口已经写好 初次布局前端需要的操作(例)
  • [hdu 3652] B-number
  • [HDU]2161Primes
  • [HNOI2008]水平可见直线
  • [JavaWeb学习] tomcat简介、安装及项目部署
  • [Latex学习笔记]数学公式基本命令