51Nod - 1119(组合数+逆元)
2018-01-29 11:22
267 查看
链接:51Nod - 1119
题意:
M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。
Input
Output
Input示例
Output示例
题解:这题数据比较大直接暴力肯定是不行咯,通过一部分打表我们不难发现这个矩阵就是由两个杨辉三角构成的,那么求f(n, m)就是求组合数c(m+n-2, m-1)%mod,其中n>=m;
我们令m+n-2=n, m-1=m, 即我们要求c(n, m)=n!/((n-m)!*m!)%mod,为了书写方便,我们再令:a=n!/(n-m)!, b=m!;
那么我们现在要求的就是:(a/b)%mod,除法取模并不能直接计算,我们需要将之转化为乘法取摸运算;
接下来我们可以有两种解法:
解法1:
(a/b)%mod=(a*b')%mod,其中b'为b%mod的乘法逆元,求乘法逆元我们直接用exgcd就好了;不过这里还有一个问题需要注意:
a, b两个数本身就已经超过long long了,所以我们不能先直接计算出a, b的值再求逆元;那么我们是否可以在计算a, b的过程中给其取摸呢?
即:((a%mod)/(b%mod))%mod=?((a%mod)*b')%mod, 答案是可以的, 因为:b=1(%mod), 那么有 b%mod=1(%mod), 显然,先给b取摸再求逆是可行的。 所以我们最终要求的就是:((a%mod)*b')%mod;
解法2:
我们先引入费马小定理:对于互质的两个数b, mod, 有:b^(mod-1)=1(%mod)-----1式;
本题要求 x=(a/b)%mod, 即: a/b=x(%mod)-----2式;
联立1,2式,有:a/b*b^(mod-1)=x(%mod), 即:a*b^(mod-2)=x(%mod), 所以:x=a*b^(mod-2) % mod, 我们可以用快速幂求解;
关于上式证明:
1式等价于:b^(mod-1)%mod=1; 即: b^(mod-1)=k*mod+1;
2式等价于:(a/b)%mod=x; 即: a/b=k'*mod+x;
所以有:a/b*b^(mod-1)=k*k'*mod^2+k'*mod+x*k*mod+x;
所以:a/b*b^(mod-1)%mod=x;
所以:a/b*b^(mod-1)=x(%mod), 即原式得证;
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
long long n, m;
void exgcd(long long a, long long b, long long& x, long long& y)
{
if(!b){
y = 0; x = 1;
return ;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
long long pow_mod(long long x, long long n)
{
long long ans = 1;
while(n){
if(n & 1) ans = ans * x % mod;
x = x * x % mod;
n >>= 1;
}
return ans;
}
int main()
{
scanf("%lld%lld", &n, &m);
if(n < m) swap(n, m);
n += m - 2; m--;
long long a = 1, b = 1, x, y;
for(long long i = n, j = 0; j < m; j++, i--) a = a * i % mod;
for(long long i = 2; i <= m; i++) b = b * i % mod;
exgcd(b, mod, x, y); //x为b对mod的逆元
x = (x % mod + mod) % mod;
printf("%lld\n", a * x % mod);
//printf("%lld\n", a * pow_mod(b, mod-2) % mod); //费马小定理
return 0;
}
题意:
M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。
Input
第1行,2个数M,N,中间用空格隔开。(2 <= m,n <= 1000000)
Output
输出走法的数量 Mod 10^9 + 7。
Input示例
2 3
Output示例
3
题解:这题数据比较大直接暴力肯定是不行咯,通过一部分打表我们不难发现这个矩阵就是由两个杨辉三角构成的,那么求f(n, m)就是求组合数c(m+n-2, m-1)%mod,其中n>=m;
我们令m+n-2=n, m-1=m, 即我们要求c(n, m)=n!/((n-m)!*m!)%mod,为了书写方便,我们再令:a=n!/(n-m)!, b=m!;
那么我们现在要求的就是:(a/b)%mod,除法取模并不能直接计算,我们需要将之转化为乘法取摸运算;
接下来我们可以有两种解法:
解法1:
(a/b)%mod=(a*b')%mod,其中b'为b%mod的乘法逆元,求乘法逆元我们直接用exgcd就好了;不过这里还有一个问题需要注意:
a, b两个数本身就已经超过long long了,所以我们不能先直接计算出a, b的值再求逆元;那么我们是否可以在计算a, b的过程中给其取摸呢?
即:((a%mod)/(b%mod))%mod=?((a%mod)*b')%mod, 答案是可以的, 因为:b=1(%mod), 那么有 b%mod=1(%mod), 显然,先给b取摸再求逆是可行的。 所以我们最终要求的就是:((a%mod)*b')%mod;
解法2:
我们先引入费马小定理:对于互质的两个数b, mod, 有:b^(mod-1)=1(%mod)-----1式;
本题要求 x=(a/b)%mod, 即: a/b=x(%mod)-----2式;
联立1,2式,有:a/b*b^(mod-1)=x(%mod), 即:a*b^(mod-2)=x(%mod), 所以:x=a*b^(mod-2) % mod, 我们可以用快速幂求解;
关于上式证明:
1式等价于:b^(mod-1)%mod=1; 即: b^(mod-1)=k*mod+1;
2式等价于:(a/b)%mod=x; 即: a/b=k'*mod+x;
所以有:a/b*b^(mod-1)=k*k'*mod^2+k'*mod+x*k*mod+x;
所以:a/b*b^(mod-1)%mod=x;
所以:a/b*b^(mod-1)=x(%mod), 即原式得证;
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
long long n, m;
void exgcd(long long a, long long b, long long& x, long long& y)
{
if(!b){
y = 0; x = 1;
return ;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
long long pow_mod(long long x, long long n)
{
long long ans = 1;
while(n){
if(n & 1) ans = ans * x % mod;
x = x * x % mod;
n >>= 1;
}
return ans;
}
int main()
{
scanf("%lld%lld", &n, &m);
if(n < m) swap(n, m);
n += m - 2; m--;
long long a = 1, b = 1, x, y;
for(long long i = n, j = 0; j < m; j++, i--) a = a * i % mod;
for(long long i = 2; i <= m; i++) b = b * i % mod;
exgcd(b, mod, x, y); //x为b对mod的逆元
x = (x % mod + mod) % mod;
printf("%lld\n", a * x % mod);
//printf("%lld\n", a * pow_mod(b, mod-2) % mod); //费马小定理
return 0;
}
相关文章推荐
- 51nod 1118 机器人走方格 解题思路:动态规划 & 1119 机器人走方格 V2 解题思路:根据杨辉三角转化问题为组合数和求逆元问题
- 2017-07-25 51nod 1119 组合数取模 某数关于质数的逆元
- 【费马小定理求逆元】51nod 1119 LightOJ 1067
- 51nod-1627 瞬间移动(组合数+逆元)
- 51nod_1118 机器人走方格(组合数+逆元)
- 51nod oj 1256 1119 1013 1083 1014 1081<组合数+逆元+快速幂,DP,枚举,树状数组>
- 【51Nod】1119 - 机器人走方格V2(逆元 & 费马小定理 & 快速幂)
- 51nod 1677 treecnt(逆元求组合数+求贡献)
- 51nod 1119 机器人走方格V2(求组合数,费马小定理+快速幂/逆元+gcd)
- 51nod 1119 机器人走方格 V2(费马小定理+快速幂 求逆元)
- 机器人走方格 V2 51Nod - 1119 组合数学+逆元
- 51nod 1119 机器人走方格 V2【组合数学+逆元】
- 第八届山东省赛 C sdut 3895 fireworks(组合数+逆元)
- 51nod 1013 3的幂的和(逆元 or 矩阵快速幂)
- 51Nod 1119 机器人走方格 V2
- LightOJ - 1102 (组合数取模逆元,当n和m小于1e6,p为任意素数时,打表法)
- 51Nod 1119 机器人走方格
- 【板子】gcd、exgcd、乘法逆元、快速幂、快速乘、筛素数、快速求逆元、组合数
- 51nod 1119 机器人走方格 V2 费马小定理求组合数
- 51nod-【1119 机器人走方格 V2】