[概率dp] Jzoj P4212 我想大声告诉你

Description

因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一些人,小R 自然也参加了。
这个游戏有n 个人参加,每一轮随机选出一个还没有出局的人x,接着x 会出局。x 在出局之后剩下的人会受到一次攻击,每一个人在遭到攻击之后会有p 的概率出局。(注意遭到攻击出局的人是不能攻击剩下的人的)
在所有人都出局之后,遭受攻击次数等于特定值的人能够成为胜者。所以现在小R 想要知道对于每一个0 <= k < n,自己恰好在遭受k 次攻击之后出局的概率是多少。(这里的出局指的不是被攻击出局)
注意在这题中,所有数值的运算在模258280327 的意义下进行。

Input

第一行输入一个正整数T 表示数据组数。
对于每一组数据输入仅一行三个数n, x, y,表示在这组数据中有n 个人参赛,p = x/y。保证y 和258280327 互质。

Output

对于每组数据,输出一行n 个整数,表示对于k = 0到n - 1 的概率在模258280327 意义下的值。

Sample Input

23 40 1009 32 1049

Sample Output

172186885 92980918 16529941229582513 163885050 39458156 102374877 116777758 216371874 55544199 95860736 8136787

Data Constraint

对于60% 的数据,n <=100
对于100% 的数据,n <= 2* 10^3,1 <= T <= 5,0<= x < y <= 10^9

题解

  • 题目大意:n个人包括主人公小R,每轮会随机等概率的踢走一个人,而剩下的人每人会有x/y的概率被干掉,而被干掉的人不能攻击剩下的人,问小R在每轮出局的概率为多少
  • 首先,我们可以知道这个问题至于小R小童鞋有关系,而剩下的n-1的小童鞋可以是等价的,也就是可以不用管它们
  • 先想想部分分的做法,对于60%的数据,我们可以设f[i][j]为剩下i个人,被攻击了j轮的概率
  • 那么就可以分成两种情况,一种是被钦定出局,一种是被干掉
  • 对于第一种直接*1/i就好了,那么对于第二种情况,可以枚举一下这次攻击会有多少个人干出局,然后算概率就好了
  • 再回来考虑一下100分做法:
  • 因为我们知道其实其他的n-1的小童鞋是等价的,不如我们就钦定它是按顺序踢人走的
  • 同样的设f[i][j]为剩下i个人,被攻击了j轮的概率
  • 那么我们还是两种情况,一种就是正常出局,那么我们是很坚强的忍受了j-1轮的严刑拷打,f[i][j]=f[i-1][j-1]*(1-p)^(j-1)
  • 另一种就是被打出去,那么我们就不能对剩下的人有任何的贡献,f[i][j]=f[i-1][j]*(1-(1-p)^j))
  • 考虑一下答案究竟是啥子东东,那么可以知道对于每一轮剩下多少个人都是有可能的
  • 这样的话,若j是固定,那就是

代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #define ll long long
 4 using namespace std;
 5 const ll N=200,mo=258280327;
 6 int n,Q;
 7 ll x,y,k,sum,ny[N],f[N][N],r,p;
 8 ll ksm(ll a,ll b){ for (r=1;b;b>>=1,a=a*a%mo) if (b&1) r=r*a%mo; return r; }
 9 int main()
10 {
11     scanf("%d",&Q);
12     while (Q--)
13     {
14         scanf("%d%lld%lld",&n,&x,&y),memset(f,0,sizeof(f)),f[1][0]=1,k=ksm(y,mo-2),p=ksm(n,mo-2),ny[0]=1;
15         for (int i=1;i<=n;i++) ny[i]=ny[i-1]*(y-x)%mo*k%mo;
16         for (int i=1;i<=n-1;i++)
17             for (int j=0;j<=n-1;j++)
18                 if (f[i][j]) f[i+1][j+1]=(f[i+1][j+1]+f[i][j]*ny[j+1]%mo)%mo,f[i+1][j]=(f[i+1][j]+f[i][j]*(1-ny[j]+mo)%mo)%mo;
19         for (int j=0;j<=n-1;j++,sum=0)
20         {
21             for (int i=1;i<=n;i++) (sum+=f[i][j])%=mo;
22             printf("%lld ",sum*p%mo);
23         }
24         printf("\n");
25     }
26 }

原文地址:https://www.cnblogs.com/Comfortable/p/10316742.html

时间: 2024-08-30 04:47:25

[概率dp] Jzoj P4212 我想大声告诉你的相关文章

[概率期望DP]JZOJ 4212 我想大声告诉你

Description 因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一些人,小R 自然也参加了.这个游戏有n 个人参加,每一轮随机选出一个还没有出局的人x,接着x 会出局.x 在出局之后剩下的人会受到一次攻击,每一个人在遭到攻击之后会有p 的概率出局.(注意遭到攻击出局的人是不能攻击剩下的人的)在所有人都出局之后,遭受攻击次数等于特定值的人能够成为胜者.所以现在小R 想要知道对于每一个0 <= k < n,自己恰好在遭受k 次攻击之后出局的概率是多

我想大声告诉你

"我想大声告诉你,对你的爱深不见底,用力紧紧抓住我们的回忆~~",I'm sorry,你想多了,我不想说love,I want to talk about English. 或许我们都有过对英语的憧憬.一时冲动,发奋图强,说"我要学好英语"."我爱英语"."我高中初中英语学的¥%##@%¥",可是这些建立的想的基础上.看上去精神境界很高.宣言很高调的语句究竟起到了how long的作用呢?--今天突然看到XX,"哇塞

[概率dp] Jzoj P2059 卡牌游戏

题目描述 N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把卡片上的数字向所有玩家展示,然后按顺时针从庄家位置数第X个人将被处决即退出游戏.然后卡片将会被放回卡牌堆里并重新洗牌.被处决的人按顺时针的下一个人将会作为下一轮的庄家.那么经过N-1轮后最后只会剩下一个人,即为本次游戏的胜者.现在你预先知道了总共有M张卡片,也知道每张卡片上的数字.现在你需要确定每个

HDU 4050 wolf5x(动态规划-概率DP)

wolf5x Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 402    Accepted Submission(s): 248 Special Judge Problem Description There are n grids in a row. The coordinates of grids are numbered fro

hdu 3853 概率DP 简单

http://acm.hdu.edu.cn/showproblem.php?pid=3853 题意:有R*C个格子,一个家伙要从(0,0)走到(R-1,C-1) 每次只有三次方向,分别是不动,向下,向右,告诉你这三个方向的概率,以及每走一步需要耗费两个能量,问你走到终点所需要耗费能量的数学期望: 回头再推次,思想跟以前的做过的类似 注意点:分母为0的处理 #include <cstdio> #include <cstring> #include <algorithm>

UVALive 6672 Bonus Cards 概率dp

题意呢 就是有两种售票方式 一种是icpc 一种是其他方式 icpc抢票成功的概率是其他方式的2倍…… 这时 一个人出现了 他通过内幕知道了两种抢票方式各有多少人 他想知道自己如果用icpc抢票成功的概率是多少 用acm抢票成功的概率是多少…… 做过不多的概率dp 还在摸索…… dp[i][j]代表第i轮有j个icpc的人已经有票了…… 当然同时i-j个通过其他方式抢票的人也有票了 这就是用同样的函数搜两次的原理…… 优化一次i<=a 一次是把初始化放到for里…… 第一次见这么卡时间的题……

1637 - Double Patience (概率DP)

一道状态较多的概率DP,想要表示所有的状态显然要拓展几个维度表示九堆牌当前的状态 . 但是这么写太复杂,所以我们不妨用一个vector来储存状态,将dp数组用一个map来表示,即 map<vector<int> ,double> d; 利用vector可以作为函数参数传递这个优点,将大大节省代码量 . 概率很好求,在每一次迭代中,寻找所有可以转移的状态数tot,那么状态转移就是d[i] = sum(d[i-1])/tot . 也就是全概率公式 . 递归边界是当所有牌都被摸走了,返回

Codeforces Div.301D Bad Luck Island(概率dp+记忆化搜索)

一道概率dp问题. 题目链接:http://codeforces.com/contest/540/problem/D 题目大意:一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j][k]来存储i个石头,j个剪刀,k个布时,某物种的存活概率,共dp三次,算出三个物种分别的概率. 首先,我们需要把对应想求的物种概率初始化,这里以石头为例,那么对于i从1到r,不难理解dp[i][0][0]=

HDU3853-LOOPS(概率DP求期望)

LOOPS Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others) Total Submission(s): 1864    Accepted Submission(s): 732 Problem Description Akemi Homura is a Mahou Shoujo (Puella Magi/Magical Girl). Homura wants to help h