扩展欧几里德 get !
从现在开始,
好好学数论
妈耶:
传送门
刚学扩欧的时候
真的是想大喊 “妈耶!这啥!”
不过,最后好歹是学会了
让我们来看看是怎么推出来的:
∴
∴
这个不是很显然,
但认真看的话还是能看懂的
好了
上模板:
int Exgcd(int a, int b, int &x, int &y)
{
if(!b)
{
x = 1;
y = 0;
return a;
}
int g = Exgcd(b,a%b,y,x);
y -= (a/b)*x;
return g;
}
int main(void)
{
cin >> a >> b;
Exgcd(a,b,x,y);
cout << (x+b)%b; //这里,为了防止出现负数进行的修正
return 0;
}
由于扩欧只是求出了一组解,
想要找到其他解的话需要不断地 x += lcm ( a , b ) / a , y += lcm ( a , b ) / b
困惑:
传送门
一道让人困惑的题。。。尤其是那个模数
如题, a / b % p 肯定是没法直接做的。
这个时候就需要逆元来求了。
先来讲讲逆元吧
b 的逆元就是 b*x ≡ 1 ( mod p ) 的解
记 b 的逆元为 b ^ ( -1 )
那么,怎么求逆元呢?
再来先来看看逆元的公式 b*x ≡ 1 ( mod p )
b*x ≡ 1 ( mod p )
即:(b*x) % p = 1
∵ a % b = (a/b)*b
也就是 a 减去整数倍的 b
∴ (b*x) % p = xb - ap
∴ xb - ap = 1
化成这样之后,就可以用扩展欧几里得求解了
这样就求出了 b 的逆元。
然后,a / b % p 也就是 a * x % p
贴代码
const int p = 19260817;
long long a,b,x,y;
long long read()
{
long long x = 0;
char c = getchar();
while(c>'9' || c<'0') c = getchar();
while(c<='9' && c>='0')
{
x = (x*10+(c-'0')) % p;
c = getchar();
}
x = x % p;
return x;
}
long long Exgcd(long long a, long long b, long long & x, long long & y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
long long g = Exgcd(b,a % b,y,x);
y -= a/b*x;
return g;
}
int main(void)
{
a = read();
b = read();
long long g = Exgcd(b,p,x,y);
if(g != 1)
{
cout << "Angry!";
return 0;
}
x = (x+p)%p;
cout << a*x % p;
return 0;
}