使用扩展欧几里得的方法解决此问题,时间上比 用快速幂求逆元快了一倍。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
/*int qmi(int a, int k, int p)
{
int res = 1;
while (k)
{
if (k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}*/
int exgcd(int a, int b, int &x, int &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y = y - (LL)a / b * x % mod;
return d;
}
int main()
{
int n;
cin >> n;
int x, y;
int a = n * 2, b = n;
int res = 1;
for (int i = a; i > a - b; i -- )
{
res = (LL)res * i % mod;
}
for (int i = 2; i <= b; i ++ )
{
exgcd(i, mod, x, y);
// cout << x<< endl;
// cout<< qmi(i, mod - 2, mod) << endl;
//res = (LL)res * qmi(i, mod - 2, mod) % mod;
res = (LL)res * x % mod;
}
exgcd(n+1, mod, x, y);
//res = (LL)res * qmi(n + 1, mod - 2, mod) % mod;
res = ((LL)res * x % mod +mod) % mod;
printf("%d",res);
return 0;
}
##将main中for循环求b!逆元可以先求b! 再用欧几里得求逆元
准确的来说res = (LL)res * x * 1/d % mod;
res = ((LL)res * x * 1 / d % mod +mod) % mod; 需要在这两个求出的逆元x乘以1/d 因为此时的x为最大公约数d时的x 需要将等号右边的d消为1
请问最后一步res = ((LL)res * x % mod +mod) % mod;为什么最后需要+mod后再整体取模
如果 res * x 的结果是一个负数,那么结果取模后仍然会得到一个负数,违反了我们要求的非负数结果
加上 mod 可以将负数转换为对应的正数值,使结果保持非负
再次对 mod 取模的目的是确保结果仍然在 [0, mod-1] 的范围内。
请问y = y - (LL)a / b * x % mod;
这里为什莫要 % mod
防止数据溢出
nb
牛逼