A. On The Way to Lucky Plaza 概率 乘法逆元
1.0 s
256 MB
standard input
standard output
Alaa is on her last day in Singapore, she wants to buy some presents to her family and friends. Alaa knows that the best present in the world will be a chocolate plate for each one of her family members and friends.
Alaa goes to Lucky Plaza shopping mall in Orchard road in order to find all chocolate she needs. Lucky Plaza is a big mall and have many shops that sell chocolate.
On the entrance of Lucky Plaza Alaa wondered if she wants to buy k chocolate plates, what is the probability that she will buy the kthchocolate plate from the nth shop she will visit, knowing that she can visit each shop at most one time. Also she can buy at most one chocolate plate from each shop, and the probability to do that is p. (This probability is the same for all shops in Lucky Plaza)
Alaa wants to finish her mission as soon as possible, so she starts visiting the shops, also she asked you to calculate the answer of her hard question. Can you?
The first line contains three integers m, n, k and real number p (1 ≤ m, n, k ≤ 105) (0 ≤ p ≤ 1), where m is the number of shops that sell chocolate in Lucky Plaza, n is the number of shops Alaa will visit, k is the number of chocolate plates Alaa wants to buy, and p is the probability that Alaa will buy a chocolate plate from any shop that sell chocolate.
The probability p is given with exactly three digits after the decimal point
On a single line print y, where y is the sought probability computed modulo 109 + 7.
The answer y is defined precisely as follows. Represent the probability that Alaa will buy the kth chocolate plate from the nth shop she will visit as an irreducible fraction p / q. The number y then must satisfy the modular equation y × q ≡ p (mod 109 + 7), and be between 0 and 109 + 6, inclusive. It can be shown that under the constraints of this problem such a number y always exists and is uniquely determined.
5 1 1 0.500
500000004
9 4 2 0.800
417600003
100 5 5 0.200
714240005
In the first test case there are 5 shops that sell chocolate in Lucky Plaza, and Alaa wants to buy only 1 chocolate plate. In this case Alaa wants to know what is the probability that she will buy the 1st chocolate plate from the 1st shop she will visit. The probability is 1 / 2, and the answer is 500000004, since (500000004 * 2) % (109 + 7) = 1 % (109 + 7).
In the second test case there are 9 shops that sell chocolate in Lucky Plaza, and Alaa wants to buy only 2 chocolate plates. In this case Alaa wants to know what is the probability that she will buy the 2nd chocolate plate from the 4th shop she will visit. The probability is 48 / 625, and the answer is 417600003, since (417600003 * 625) % (109 + 7) = 48 % (109 + 7).
题解:博客
概率,线性递推求乘法逆元。
找到公式,就是求a*b%mod=C(n-1,k-1)*p^k*(1-p)^n-k%mod
转化成a=C(n-1,k-1)*p^k*(1-p)^n-k*inv(b)%mod;
先把p转化成一个long long的类型,注意a消除浮点误差,然后就是用杨辉三角求出组合数,最后就是求b的乘法逆元。
这里要注意的地方有不能直接用杨辉三角把组合数求出来,因为中间可能会超过mod,所以还是要一步一步的递推过去,然后再乘以一个乘法逆元。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
const int mod = 1e9 + 7;
const double eps = 1e-10;
ll inv[maxn]; int main()
{
int m, n, k;
double p;
inv[1] = 1;
for (int i = 2; i < maxn; i++) inv[i] = (mod - mod / i)*1ll*inv[mod%i]%mod; cin >> m >> n >> k >> p;
if(m<n||k>n)
{
printf("0\n");
return 0;
}
ll p1 = p * 1000 + eps,ans=1;
//求组合数
for (int i = 1; i <= k - 1; i++) ans = ans * (n - i) % mod;
for (int i = 1; i <= k - 1; i++) ans = ans * inv[i] % mod; for (int i = 1; i <= k; i++) ans = ans * p1%mod;
for (int i = 1; i <= n - k; i++) ans = ans * (1000 - p1) % mod; for (int i = 1; i <= n; i++) ans = ans * inv[1000] % mod; printf("%lld\n", ans);
return 0;
}
然后介绍一下三种求乘法逆元的方法:
乘法逆元
对于两个数a,p若gcd(a,p)=1则一定存在另一个数b,使得ab≡1(modp),并称此时的b为a关于1模p的乘法逆元。我们记此时的b为inv(a)或 。 举个例子:5×3≡1(mod14),我们称此时的3为5关于1模14的乘法逆元。 如何求乘法逆元?
方法一:费马小定理
费马小定理:当有两数a,p满足gcd(a,p)=1时,则有ap≡a(modp)。
变一下形:a* ≡1(modp)。是不是和上面的乘法逆元的定义是相似的?
所以,我们可以使用快速幂求出 ,即求出a的逆元。
long long PowMod(long long a,int b) {
long long ret=1;
while(b) {
if(b&1)ret=ret*a%Mod; //b&1 在这里和b%2 的含义一样
a=a*a%Mod;
b>>=1;
}
return ret;
} 方法二:扩展欧几里得算法
由定义可知:ab≡1(modp),这个式子等价于已知a,p求一个二元一次不定方程ab=kp+1,移一下项得:ab−kp=1。这东西不是扩展欧几里得算法?
long long extend_gcd(long long a,long long b,long long &x,long long &y) {
if(a==0&&b==0)
return -1;
if(b==0)
{
x=1;
y=0;
return a;
}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
long long mod_reverse(long long a,long long n) {
long long x,y,d=extend_gcd(a,n,x,y);
if(d==1) {
if(x%n<=0)return x%n+n;
else return x%n;
} else return -1;
} 方法三:递推计算阶乘的逆元
当我们要计算一大串连续的阶乘的逆元时,采用费马小定理或扩展欧几里得算法就有可能超时,所以我们必须采用一个更快的算法。
令 ,则可得:
(mod p)
我们将(i+1)(i+1)乘过去,则有:
(mod p)
自然我们就得出递推式。
乘法逆元的作用?
我们由费马小定理可得:a* ≡1(modp)。
所以:
≡ ≡1/a(modp)
我们又知道模运算的乘法结合律:
a/b≡b* ≡b* (modp)
所以我们可以知道:a除以一个数模p,等于a乘这个数的乘法逆元模p。
f[0]=1;
for(int i=1;i<=N;i++)
f[i]=f[i-1]*i%Mod;
inv[0]=1;
inv[N]=PowMod(f[N],Mod-2);
for(int i=N-1;i>0;i--)
inv[i]=inv[i+1]*(i+1)%Mod; 下为几种方法求逆元的代码实现
int inv[1000010];
LL ksm(LL a,LL b,LL mod)
{
int ans=1;
while(b)
{
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
LL GCD=exgcd(b,a%b,x,y);
LL tmp=x;
x=y;
y=tmp-a/b*y;
return GCD;
}
LL inv1(LL a,LL mod)//扩展欧几里得求逆元
{
LL x,y;
LL d=exgcd(a,mod,x,y);
if(d==1) return (x%mod+mod)%mod;
return -1;
}
LL inv2(LL a,LL mod)//费马小定理
{
return ksm(a,mod-2,mod);
}
void inv3(LL mod)//线性递推求逆元
{
inv[1]=1;
for(int i=2;i<=mod-1;i++)
{
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
cout<<inv[i]<<" ";
}
}
int main()
{
LL n,mod;
while(cin>>n>>mod)
{
cout<<inv1(n,mod)<<" "<<inv2(n,mod)<<endl;
inv3(mod);
}
}
然后再加一个杨辉三角求组合数:
组合数:
按照杨辉三角(递推):
memset(c,0,sizeof(c));
for (int i=0; i<=n; i++){
c[i][0]=1;
for (int j=1; j<=i; j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
优化形式---利用 :
c[0]=1;
for (int i=1; i<=n; i++) c[i]=c[i-1]*(n-i+1)/i;
A. On The Way to Lucky Plaza 概率 乘法逆元的更多相关文章
- Codeforces gym 101343 A. On The Way to Lucky Plaza【概率+逆元+精度问题】
2017 JUST Programming Contest 2.0 题目链接:http://codeforces.com/gym/101343/problem/A A. On The Way to ...
- HDU5985 Lucky Coins 概率dp
题意:给你N种硬币,每种硬币有Si个,有Pi 概率朝上,每次抛所有硬币抛起,所有反面的拿掉,问每种硬币成为最后的lucky硬币的概率. 题解:都知道是概率dp,但是模拟赛时思路非常模糊,很纠结,dp[ ...
- HDU 5985/nowcoder 207D - Lucky Coins - [概率题]
题目链接:https://www.nowcoder.com/acm/contest/207/D 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5985 ...
- HDU.5985.Lucky Coins(概率DP)
题目链接 \(Description\) 有n(n<=10)种硬币,已知每种硬币的数量和它抛一次正面朝上的概率pi.进行如下过程:每次抛一次所有硬币,将正面朝下的硬币去掉.重复该过程直到只剩一种 ...
- 【BZOJ】3566: [SHOI2014]概率充电器
[算法]树型DP+期望DP [题意]一棵树上每个点均有直接充电概率qi%,每条边有导电概率pi%,问期望有多少结点处于充电状态? [题解]引用自:[BZOJ3566][SHOI2014]概率充电器 树 ...
- 算法讲堂二:组合数学 & 概率期望DP
组合数学 1. 排列组合 1. 加法原理 完成一列事的方法有 n 类,其中第 i 类方法包括\(a_i\)种不同的方法,且这些方法互不重合,则完成这件事共有 \(a_1 + a_2 + \cdots ...
- gym101343 2017 JUST Programming Contest 2.0
A.On The Way to Lucky Plaza (数论)题意:m个店 每个店可以买一个小球的概率为p 求恰好在第m个店买到k个小球的概率 题解:求在前m-1个店买k-1个球再*p ...
- POJ 2472 106 miles to Chicago(Dijstra变形——史上最坑的最长路问题)
题目链接 :http://poj.org/problem?id=2472 Description In the movie "Blues Brothers", the orphan ...
- 2017 JUST Programming Contest 2.0 题解
[题目链接] A - On The Way to Lucky Plaza 首先,$n>m$或$k>m$或$k>n$就无解. 设$p = \frac{A}{B}$,$ans = C_{ ...
随机推荐
- Javascript继承5:如虎添翼----寄生式继承
/* * 寄生式继承 * 其实就是对原型继承的第二次封装,在封装过程中对继承的对象进行了扩展. * 也存在原型继承的缺点!! * 这种思想的作用也是为了寄生组合式继承模式的实现. */ //声明基对象 ...
- 2018-08-06 在Office的VBA代码里中文命名
在Excel处理数据时, 顺便试了一下VBA代码编辑器里输入中文, 结果显示为乱码. 查了一下发现VBA本身支持Unicode, 但需要设置系统配置使编辑器能够正常显示, 即设置简体中文为Curren ...
- Linux PCI设备驱动的实现思路与思想
概述 1.PCI设备一般都具有双重身份,一方面作为PCI设备注册到Linux内核,另一方面,作为字符设备或者块设备,或者网络设备注册到Linux内核,所以,在看PCI设备时一定要注意到这点. 2. 一 ...
- ThinkPHP框架知识
php框架 一.真实项目开发步骤: 多人同时开发项目,协作开发项目.分工合理.效率有提高(代码风格不一样.分工不好) 测试阶段 上线运行 对项目进行维护.修改.升级(单个人维护项目,十分困难,代码风格 ...
- 小程序实践(三):九宫格实现及item跳转
效果图: 实现效果图红色线包含部分的九宫格效果,并附带item点击时间. --------------------------------------------------------------- ...
- Android内存优化(五) Lint代码扫描工具
1.使用 工具栏 -> Analyze -> Inspect Code… 点击 Inspect Code 后会弹出检查范围的对话框: 默认是检查整个项目,我们可以点击 Custom sc ...
- 微信小程序 text属性设置 WXSS样式
>微信小程序的布局css样式 参考自 珺L 文字 width: fit-content;font-size:20px; /*设置文字字号*/color:red; ...
- python--线程同步原语
Threading模块是python3里面的多线程模块,模块内集成了许多的类,其中包括Thread,Condition,Event,Lock,Rlock,Semaphore,Timer等等.下面这篇文 ...
- MVC框架与三层架构
MVC框架 介绍: MVC全名Model View Controller Model:模型的意思,代表业务模型 View:视图的意思,代表用户界面 Controller:控制器的意思,控制器接受用户的 ...
- Docker Compose 安装 on centos7
本文演示如何在CentOS7上安装Docker Compose. 1 在线安装 1.1 下载安装包 $ curl -L https://github.com/docker/compose/releas ...