怎么说,看了推到之后真的不难,事实上确实也蛮友好(可能咱就是想不出多项式题目的做法???),除了用到了分治法法塔就比较毒瘤

花了一个晚上以及一个上午做这么一道题...(还是太菜了)

Result1

分治法法塔NB ,CMX NB

推导分为两步走:

Part1

第一步是求出游戏人数为 n 时,第一个人最后死亡的概率 \(f(n)\)

我们先写出 f 的公式:

\[f_n=\sum_{i=0}^{n-1} f_{n-i} \binom{n-1}{i} p^i q^{n-i}
\]

其中 i 为一轮下来死亡的人数,当然 1 号必然要存活

化简:

\[\begin{aligned}{f_n}({1-q^n})&=\sum_{i=1}^{n-1} f_{n-i} \binom{n-1}{i} p^i q^{n-i} \\ f_n&=\frac{n!}{1-q^n} \sum_{i=1}^{n-1} \frac{p^i}{i!} ·\frac{f_{n-i}q^{n-i}}{(n-1-i)!} \end{aligned}
\]

容易看出是个卷积的形式,但 f 卷积式与自己有关,所以用分治法法塔解决,复杂度直上 \(n\log^2n\)

这样乱搞就是为了求出一个 \(f_n\) ?呵呵...

Part2

然后康康对于每个人他留到最后的概率

由于判定是从第一号角色开始的,那么我们把第 k 个人先搞到第一号角色,即假设先判了前面的 k-1 个人,死了 i 个,剩 n-i 个,这时候第 k 个人就是最先判定的那个了

\[\begin{aligned}S_k&=\sum_{i=0}^{k-1} \binom{k-1}{i} p^{i} q^{k-1-i} f_{n-i} \\ &=(k-1)!\sum_{i=0}^{k-1} \frac{p^if_{n-i}}{i!} · \frac{q^{k-1-i}}{(k-1-i)!} \end{aligned}
\]

发现是个蛮朴素卷积...

Code

好菜的 zjq...

  1. //by Judge (zlw ak ioi)
  2. #include<bits/stdc++.h>
  3. #define Rg register
  4. #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
  5. #define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
  6. #define ll long long
  7. using namespace std;
  8. const int mod=998244353;
  9. const int iG=332748118;
  10. const int M=53e4+3;
  11. typedef int arr[M];
  12. int n,a,b,p,q,limit; arr f,A,B,r,fac,finv,inv,pwp,pwq;
  13. char sr[1<<21],z[20];int CCF=-1,Z;
  14. inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
  15. inline void print(int x,char chr='\n'){
  16. if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
  17. while(z[++Z]=x%10+48,x/=10);
  18. while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
  19. }
  20. inline int mul(int x,int y){return 1ll*x*y%mod;}
  21. inline void Pls(int& x,int y){if((x+=y)>=mod)x-=mod;}
  22. inline int inc(int x,int y){return (x+=y)>=mod?x-mod:x;}
  23. inline int qpow(int x,int p=mod-2){ Rg int s=1;
  24. for(;p;p>>=1,x=mul(x,x)) if(p&1) s=mul(s,x); return s;
  25. }
  26. inline void init(int n){ Rg int len=-1;
  27. limit=1; while(limit<n) limit<<=1,++len;
  28. fp(i,1,limit-1) r[i]=(r[i>>1]>>1)|((i&1)<<len);
  29. }
  30. inline void NTT(int* a,int tp){
  31. fp(i,1,limit-1) if(i<r[i]) swap(a[i],a[r[i]]);
  32. for(Rg int i=1,I=2;i<limit;i<<=1,I<<=1){
  33. Rg int Wn=qpow(tp?3:iG,(mod-1)/I);
  34. for(Rg int j=0,y;j<limit;j+=I)
  35. for(Rg int k=0,w=1;k<i;++k,w=mul(w,Wn)){
  36. y=mul(a[j+k+i],w),a[j+k+i]=inc(a[j+k],mod-y),
  37. a[j+k]=inc(a[j+k],y);
  38. }
  39. } if(!tp) fp(i,0,limit-1) a[i]=mul(a[i],inv[limit]);
  40. }
  41. inline void Solv(int l,int r){ if(r==1) return ;
  42. if(l==r) return f[l]=mul(f[l],mul(fac[l-1],qpow(mod+1-pwq[l]))),void();
  43. Rg int md=(l+r)>>1; Solv(l,md),init(md+r-l-l);
  44. fp(i,l,md) A[i-l]=mul(f[i],mul(pwq[i],finv[i-1]));
  45. fp(i,1,r-l) B[i-1]=mul(pwp[i],finv[i]);
  46. fp(i,md-l+1,limit-1) A[i]=0; fp(i,r-l,limit-1) B[i]=0;
  47. NTT(A,1),NTT(B,1); fp(i,0,limit-1) A[i]=mul(A[i],B[i]);
  48. NTT(A,0); fp(i,md+1,r) Pls(f[i],A[i-l-1]); Solv(md+1,r);
  49. }
  50. inline void Calc(){ init(n<<1);
  51. fp(i,0,n-1) A[i]=mul(f[n-i],mul(pwp[i],finv[i])),B[i]=mul(pwq[i],finv[i]);
  52. fp(i,n,limit-1) A[i]=B[i]=0; NTT(A,1),NTT(B,1);
  53. fp(i,0,limit-1) A[i]=mul(A[i],B[i]); NTT(A,0);
  54. fp(i,0,n-1) print(mul(A[i],fac[i])); Ot();
  55. }
  56. int main(){ cin>>n>>a>>b,p=mul(a,qpow(b)),q=mul(b-a,qpow(b));
  57. init(n<<1),fac[0]=1; fp(i,1,limit) fac[i]=mul(fac[i-1],i);
  58. finv[limit]=qpow(fac[limit]); fd(i,limit,1) finv[i-1]=mul(finv[i],i);
  59. inv[0]=1; fp(i,1,limit) inv[i]=mul(finv[i],fac[i-1]);
  60. pwp[0]=pwq[0]=1; fp(i,1,n) pwp[i]=mul(pwp[i-1],p),pwq[i]=mul(pwq[i-1],q);
  61. return f[0]=0,f[1]=1,Solv(1,n),Calc(),0;
  62. }

Result 2

嘤嘤嘤发现这个分治法法塔被 一只 log 的血腥推导吊打... 清雨姐姐NB

首先用 i 表示游戏进行了 i 轮之后, 1 号位 死了,且是最后死的概率(可能有点难理解 1 号位为什么要死,原因大概是因为是不这么算的话比较难表示,且容易出现相同的状况重复计算)

\[\begin{aligned}f_n&=\sum_{i=0}^{\infty}p· q^i (1-q^i)^{n-1}\\&= \sum_{i=0}^{\infty}p· q^i \sum_{j=0}^{n-1} (-1)^{j} \binom{n-1}{j}(q^i)^{j}\\&=p \sum_{j=0}^{n-1}\binom{n-1}{j} (-1)^{j} \sum_{i=0}^{\infty} (q^i)^{j+1} \\&=p\sum_{j=0}^{n-1}\frac{\binom{n-1}{j} (-1)^{j} }{1-q^{j+1}} \\&=p (n-1)!\sum_{j=0}^{n-1}\frac{ (-1)^{j} }{j!·(1-q^{j+1})} · \frac{1}{(n-1-j)!} \end{aligned}
\]

发现也是卷积的形式呢,而且直接一只 log 就能处理出来,然后咱用 \(f_n\) 进行上述的操作就行了QwQ

  1. //by Judge (zlw ak ioi)
  2. #include<bits/stdc++.h>
  3. #define Rg register
  4. #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
  5. #define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
  6. #define ll long long
  7. using namespace std;
  8. const int mod=998244353;
  9. const int iG=332748118;
  10. const int M=53e4+3;
  11. typedef int arr[M];
  12. int n,a,b,p,q,limit; arr f,A,B,r,fac,finv,inv,pwp,pwq;
  13. char sr[1<<21],z[20];int CCF=-1,Z;
  14. inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
  15. inline void print(int x,char chr='\n'){
  16. if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
  17. while(z[++Z]=x%10+48,x/=10);
  18. while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
  19. }
  20. inline int mul(int x,int y){return 1ll*x*y%mod;}
  21. inline void Pls(int& x,int y){if((x+=y)>=mod)x-=mod;}
  22. inline int inc(int x,int y){return (x+=y)>=mod?x-mod:x;}
  23. inline int qpow(int x,int p=mod-2){ Rg int s=1;
  24. for(;p;p>>=1,x=mul(x,x)) if(p&1) s=mul(s,x); return s;
  25. }
  26. inline void init(int n){ Rg int len=-1;
  27. limit=1; while(limit<n) limit<<=1,++len;
  28. fp(i,1,limit-1) r[i]=(r[i>>1]>>1)|((i&1)<<len);
  29. }
  30. inline void NTT(int* a,int tp){
  31. fp(i,1,limit-1) if(i<r[i]) swap(a[i],a[r[i]]);
  32. for(Rg int i=1,I=2;i<limit;i<<=1,I<<=1){
  33. Rg int Wn=qpow(tp?3:iG,(mod-1)/I);
  34. for(Rg int j=0,y;j<limit;j+=I)
  35. for(Rg int k=0,w=1;k<i;++k){
  36. y=mul(a[j+k+i],w),a[j+k+i]=inc(a[j+k],mod-y),
  37. a[j+k]=inc(a[j+k],y),w=mul(w,Wn);
  38. }
  39. } if(!tp) fp(i,0,limit-1) a[i]=mul(a[i],inv[limit]);
  40. }
  41. inline void Calc(){ init(n<<1);
  42. fp(i,0,n-1) A[i]=mul(mul(i&1?mod-1:1,qpow(mod+1-pwq[i+1])),finv[i]),B[i]=finv[i];
  43. NTT(A,1),NTT(B,1); fp(i,0,limit-1) A[i]=mul(A[i],B[i]); NTT(A,0);
  44. fp(i,1,n) f[i]=mul(mul(p,fac[i-1]),A[i-1]);
  45. memset(A,0,(limit+1)<<2),memset(B,0,(limit+1)<<2);
  46. fp(i,0,n-1) A[i]=mul(f[n-i],mul(pwp[i],finv[i])),B[i]=mul(pwq[i],finv[i]);
  47. NTT(A,1),NTT(B,1); fp(i,0,limit-1) A[i]=mul(A[i],B[i]); NTT(A,0);
  48. fp(i,0,n-1) print(mul(A[i],fac[i])); Ot();
  49. }
  50. int main(){ cin>>n>>a>>b,p=mul(a,qpow(b)),q=mul(b-a,qpow(b));
  51. init(n<<1),fac[0]=1; fp(i,1,limit) fac[i]=mul(fac[i-1],i);
  52. finv[limit]=qpow(fac[limit]); fd(i,limit,1) finv[i-1]=mul(finv[i],i);
  53. inv[0]=1; fp(i,1,limit) inv[i]=mul(finv[i],fac[i-1]);
  54. pwp[0]=pwq[0]=1; fp(i,1,n) pwp[i]=mul(pwp[i-1],p),pwq[i]=mul(pwq[i-1],q);
  55. return f[0]=0,Calc(),0;
  56. }

Comet OJ - Contest #5 E 迫真大游戏的更多相关文章

  1. Comet OJ - Contest #5 D 迫真小游戏 (堆+set)

    迫真小游戏 已经提交 已经通过 时间限制:2000ms 内存限制:256MB 73.98% 提交人数:196 通过人数:145 题目描述 H君喜欢在阳台晒太阳,闲暇之余他会玩一些塔防小游戏. H君玩的 ...

  2. 【杂题】【CometOJ Contest #5】E:迫真大游戏【概率】【排列组合】【多项式】

    Description 有一个n个点的环,有一个指针会从1号点开始向后扫描,每次扫描有p的概率删除当前点 询问每个点最后一个被删除的概率. 答案对998244353取模 n<=200000 So ...

  3. Comet OJ - Contest #5 简要题解

    好久没更博了,还是象征性地更一次. 依然延续了简要题解的风格. 题目链接 https://cometoj.com/contest/46 题解 A. 迫真字符串 记 \(s_i\) 表示数字 \(i\) ...

  4. Comet OJ - Contest #11 题解&赛后总结

    Solution of Comet OJ - Contest #11 A.eon -Problem designed by Starria- 在模 10 意义下,答案变为最大数的最低位(即原数数位的最 ...

  5. Comet OJ - Contest #5

    Comet OJ - Contest #5 总有一天,我会拿掉给\(dyj\)的小裙子的. A 显然 \(ans = min(cnt_1/3,cnt_4/2,cnt5)\) B 我们可以感性理解一下, ...

  6. Comet OJ - Contest #2 简要题解

    Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...

  7. Comet OJ - Contest #2简要题解

    Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...

  8. Comet OJ - Contest #4--前缀和

    原题:Comet OJ - Contest #4-B https://www.cometoj.com/contest/39/problem/B?problem_id=1577传送门 一开始就想着暴力打 ...

  9. Comet OJ - Contest #8

    Comet OJ - Contest #8 传送门 A.杀手皇后 签到. Code #include <bits/stdc++.h> using namespace std; typede ...

随机推荐

  1. DIY Arduino 方向盘

    之前的项目中使用Arduino做UE4的输入设备时候需要用到UE4Duino这个插件,以字符串的形式从Arduino中组装信息并发送到串口,使用UE4Duino进行解析,过程比较麻烦. 最近发现的一个 ...

  2. C++入门经典-例2.14-使用移位运算

    1:代码如下: // 2.14.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usin ...

  3. 网络1911、1912 C语言第1次作业批改总结

    一.评分规则 重点检查大家代码规范,变量名.大括号换行.缩进等发现不规范倒扣3分. 助教会进PTA查看大家代码的提交列表,发现不规范或抄袭,均扣分 每次作业完成后,至少邀请3个同学点评. 原作业地址: ...

  4. 5、kubernetes资源清单之Pod应用190709

    一.Pod镜像及端口 获取帮助文档 # kubectl explain pod.spec.containers spec.containers <[]object> pod.spec.co ...

  5. LeetCode 46. 全排列(Permutations)

    题目描述 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [ ...

  6. java基本类型对齐

    1.Java 基本数据类型和精度 整数数据类型 关键字 描述 大小 格式 byte 字节长度整数 8 位二进制补码 从 +127 到 -128 short 短整型 16 位二进制补码 从 +32767 ...

  7. Note: Time clocks and the ordering of events in a distributed system

    http://research.microsoft.com/en-us/um/people/lamport/pubs/time-clocks.pdf 分布式系统的时钟同步是一个非常困难的问题,this ...

  8. layui数据加载中遮罩层的实现

    1.load方法提供三种风格供选择. 方法一:loadIndex = layer.load(); //不传参,默认0 方法二:loadIndex = layer.load(1); // 1,另外一种风 ...

  9. 实现一个可以用 await 异步等待的 Awaiter

    总结起来,要想使一个方法可被 await 等待,必须具备以下条件: 这个方法返回一个类 A 的实例,这个类 A 必须满足后面的条件.此类 A 有一个可被访问到的 GetAwaiter 方法(扩展方法也 ...

  10. leetcode 160相交链表

    暴力解法当然可以遍历两个链表,不过time O(mn) space O(1)暂且不说, 方法一:双指针, time O(m+n),space O(1) 可以对比判断环形链表的快慢指针法. 这种方法构思 ...