洛谷P2265题解
题目描述
一个
引入
逆元
1.什么是逆元?
若有线性同余方程
2.逆元怎么求?
由逆元的定义有:
由费马小定理有:
注意:求逆元还可以用扩展欧几里得法。
3.逆元的基本应用
组合数
1.什么是组合数?
从
2.组合数如何求?
- 模拟:
按照组合数的定义暴力计算即可,但是这样肯定会爆 long long,最多过
n\leq12 的数据。 - 杨辉三角:
观察下面的图片,若把第
i 行第j 个数记为f(i-1,j-1) ,则\dbinom{i}{j}=f(i,j) ,利用这种递推的思想,我们可以过掉n\leq100 的数据。
- 逆元求组合数:
运用上述知识,对于一个组合数
\dbinom{p}{q}=\dfrac{\begin{matrix} \prod_{i=p-q+1}^p i \end{matrix}}{\begin{matrix} \prod_{i=1}^p i \end{matrix}} ,分数线上方的数直接相乘,分数线下方的数都乘其逆元即可。题解
分析
回归本题,因为每一步只能向左或向上走,所以总步数为
(1,1) 到(n,m) 的曼哈顿距离,即总的步数为定值(n+m) 。接下来考虑从这(n+m) 步中任意选m 步向左,根据组合数的定义,答案为\dbinom{n+m}{m} 。然后组合数用逆元求值即可。代码
#include<bits/stdc++.h> using namespace std; const long long mod=1e9+7; long long n,m,ans=1; long long quickpow(long long a,long long b)//快速幂 { long long res=1; while(b) { if(b&1) res=res*a%mod; b>>=1; a=a*a%mod; } return res; } int main() { scanf("%lld%lld",&n,&m); for(long long i=n+1;i<=n+m;i++) ans=ans*i%mod;//分数线上方直接乘 for(long long i=2;i<=m;i++) ans=ans*quickpow(i,mod-2)%mod;//分数线下方乘逆元 printf("%lld\n",ans); return 0; }