题意: 有一矩形n * m,从左上走到右下有多少种走法
分析:首先可以明确,水平要走m-1格,竖直要走n-1格,则走到目的地的任意一条路径必须走n+m-2格,只要确定竖直要走的,剩下的就是水平要走的,则答案为
费马小定理
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define d(x) cout << (x) << endl
#pragma GCC diagnostic error "-std=c++11"
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 1e4 + 10;
ll jc[N];
ll pow(ll x, ll y)
{
ll ans = 1;
while(y){
if(y&1)
ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
ll C(ll n, ll m)
{
return jc[n] * pow(jc[m], mod - 2) % mod * pow(jc[n - m], mod - 2) % mod ;
}
int main()
{
jc[0] = jc[1] = 1;
for(int i = 2; i < N; i++){
jc[i] = jc[i - 1] * i % mod;
}
int n, m;
scanf("%d%d", &n, &m);
printf("%lld\n", C(n + m - 2, max(n-1, m-1)));
return 0;
}
扩展欧几里得求逆元
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
void ex_gcd(LL a, LL b, LL &d, LL &x, LL &y){
if(b==0){
x =1; y=0 ; d = a;
return ;
}
ex_gcd(b, a%b, d, y, x);
y -= x*(a/b);
}
//乘法逆元 ax = 1(mod m)
LL inverse(LL a, LL m){
LL x, y, d;
ex_gcd( a, m, d, x, y);
if(d!=1) return 0;
return (x%m + m)%m;
}
LL comb(LL m, LL n){
LL t1 =1, t2=1;
for(LL i = n-m+1 ; i<=n ; ++i) t1 = t1*i%mod;
for(LL i = 1 ; i<=m ; ++i) t2 = t2*i%mod;
return t1*inverse(t2, mod)%mod;
}
int main(){
int a, b;
cin>> a >> b;
cout<<comb(max(a-1, b-1), a+b-2)%mod<<endl;
}