求逆元
相关定理
费马小定理,有
。 因此 方程
的解被称为a关于模p的逆元。当p为素数且 (此时必有解且唯一)时,由费马小定理可得 。 例如:
可以转化为
求逆元方法:
通过扩展欧几里得算法求逆元
cpp
// when we used this method to calculate x / y % p, we also need x and p is coprime
// Method 1: Extended Euclid
// Requires: a and b is coprime
// Modify: x, y
// Effects: when the method is finished, x is a's inverse element about b.
// Return: gcd(a, b)
int ex_gcd(int a, int b, int &x, int &y) {
int ret, tmp;
if (b == 0) {
x = 1;
y = 0;
return a;
}
ret = ex_gcd(b, a % b, x, y);
tmp = x;
x = y;
y = tmp - a / b * y;
return ret;
}通过递推求1~n的逆元
这个算法可以在
cpp
// when we used this method to calculate x / y % p, we also need x and p is coprime
// Method 3: Recursive to get i's inverse element
// Requires: p is prime and p != 2
// Modify: inv[]
// Effects: inv[i] is i's inverse element about p;
int inv[N];
void get_inverse(int n, int p) {
inv[1] = 1;
for (int i = 2; i <= n; ++i) {
inv[i] = (p - p / i) * inv[p % i] % p;
}
}阶乘的逆元:
cpp
// when we used this method to calculate x / y % p, we also need x and p is coprime
// Method 4: Recursive to get Factorial[i] and their inverse element
// Requires: p is prime
// Modify: invf[], factor[]
// Effects: factor[i] is i's factorial, invf[i] is factor[i]'s inverse element
int invf[N], factor[N];
void get_factorial_inverse(int n, int p) {
factor[0] = 1;
for (int i = 1; i <= n; ++i) {
factor[i] = i * factor[i - 1] % p;
}
invf[n] = quick_inverse(factor[n], p);
for (int i = n-1; i >= 0; --i) {
invf[i] = invf[i + 1] * (i + 1) % p;
}
}我们要从
因为
首先求出一个数模p的逆元:
然后再递推出
可以得到
然后就可以求出组合数了
代码
cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll N=200000+20;
ll fac[N]= {1,1},inv[N]= {1,1},f[N]= {1,1};
/*
fac[i]:i的阶乘
inv[i]:i的阶乘的逆元
f[i]:i的逆元
*/
ll C(ll a,ll b)//除以一个数等于乘这个数的逆元
{
return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void init()
{
for(ll i=2; i<N; i++)
{
fac[i]=fac[i-1]*i%mod;
f[i]=(mod-mod/i)*f[mod%i]%mod;
inv[i]=inv[i-1]*f[i]%mod;
}
}
int main()
{
ll n,m;
init();
while(cin>>n>>m)
cout<<C(m+n-4,m-2)<<endl;
return 0;
}