题目描述
给出一个有理数 c = a b c=\frac{a}{b} c=ba,求 c m o d 19260817 c \bmod 19260817 cmod19260817 的值。
这个值被定义为 b x ≡ a ( m o d 19260817 ) bx\equiv a\pmod{19260817} bx≡a(mod19260817) 的解。
题目思路
这道题要用到扩展欧几里得(还有亿点裴蜀定理)加上快读+逆元来做(快读来实现逆元操作),不知道的请先去了解再来看本题解。
下面是扩展欧几里得求解的过程:
假设我们现在知道了另外一组数x1和y1它们满足bx1+(a mod b)y1=gcd(a, b)
它们会满足 ax+by= bx1+(a mod b)y1
需要求出ab的xy
首先,我们知道取模运算的一个性质:(a mod b)=a-b*(a/b)
所以我们可以把bx1+(a mod b)y1变为 bx1+(a-b*(a/b))*y1
拆括号变成bx1+ay1-b*(a/b)y1
再把b提取出来变成ay1+b(x1-(a/b)y1)
然后再带到方程里 ax+by=ay1+b(x1-(a/b)y1)
就会得到x=y1,y=(x1-(a/b)y1) 两个式子
也就是说我们只要求出x1和y1就能求出x和y
那么如何求x1和y1呢 同理计算bx2+(a mod b)y2=gcd(b, b%a)中的x2和y2
直到最后b变为0,再推回去就好了。
快读(逆元版)
ll read(){
ll num=0;
char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)){//实现逆元操作
num=num*10+c-'0';
num%=M;//每一回都要求模
c=getchar();
}
return num;
}
扩展欧几里得代码
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1;y=0;
return a;
}
ll g=exgcd(b,a%b,x,y);
ll z=x;x=y;y=z-a/b*y;
return g;
}
下面是完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=19260817;
ll read(){
ll num=0;
char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)){
num=num*10+c-'0';
num%=M;
c=getchar();
}
return num;
}
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){//算法递归到终点(b变为0)反推求解xy为1和0
x=1;y=0;
return a;
}
ll g=exgcd(b,a%b,x,y);
ll z=x;x=y;y=z-a/b*y;
return g;
}
int main()
{
string s1,s2;
ll na=0,nb=0;
na=read();
nb=read();
//na/nb
//nb在 %M 下的逆元
ll a=nb,b=M;
ll x,y;
ll g=exgcd(a,b,x,y);
if(g!=1){
cout<<"Angry!";
}else{
x=(x%b+b)%b;
cout<<na*x%M;
}
return 0;
}
//freopen("ans.in","r",stdin);
//freopen("ans.out","w",stdout);
//cout<<fixed<<setprecision(2)<<c;