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_{ ...
随机推荐
- ____利用C#特性Attribute完成对sql语句的拼接
//定义 特性类: public class MyAttribute : Attribute//自定义注解类判断是否是主键 { public bool PrimaryKey = false; publ ...
- WPF 绕圈进度条(一)
在设计界面时,有时会遇到进度条,本次讲解如何设计自定义的绕圈进度条,直接上代码: 1.控件界面 <UserControl x:Class="ProgressBarControl&quo ...
- 将汉字转化为拼音的js插件
/*---------------------------------------------------------------- // 文件名:chinese2pinyin.js // 文件功能描 ...
- springMVC_03注解完成hello案例
1.导入jar包 commons-logging-1.1.1.jar jackson-annotations-2.5.4.jar jackson-core-2.5.4.jar jackson-data ...
- Retrofit2 原理解析
Retrofit是什么 官网介绍是A type-safe HTTP client for Android and Java,是一个 RESTful 的 HTTP 网络请求框架的封装,但网络请求不是Re ...
- 应用分类&练手项目计划
应用分类 练手项目 [应用] 通讯录 xx管理 聊天室 [组件] web容器 db 中间件
- mybatis缓存机制
目录 mybatis缓存机制 Executor和缓存 一级缓存 小结 二级缓存 小结 mybatis缓存机制 mybatis支持一.二级缓存来提高查询效率,能够正确的使用缓存的前提是熟悉mybatis ...
- springboot 数据验证
不能相信前端传过来的任何数据 一定不能相信前端传过来的任何数据 绝对不能相信前端传过来的任何数据 @JsonFormat 时间必须是指定的格式(这里是接收参数格式,不是取数据来格式化) @Null 必 ...
- 数据库连接池(基于MySQL数据库)
使用JDBC是怎么保证数据库客户端和数据库服务端进行连接的? 通过代码: conn=DriverManager.getConnection(url, username, password); JDBC ...
- iOS------获取当前时间和当前时间戳
//获取当前的时间 +(NSString*)getCurrentTimes{ NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; ...