【模板】有理数取余
题目描述
给出一个有理数 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) 的解。
输入格式
一共两行。
第一行,一个整数
a
a
a。
第二行,一个整数
b
b
b。
输出格式
一个整数,代表求余后的结果。如果无解,输出 Angry!
。
样例 #1
样例输入 #1
233
666
样例输出 #1
18595654
提示
对于所有数据,保证 0 ≤ a ≤ 1 0 10001 0\leq a \leq 10^{10001} 0≤a≤1010001, 1 ≤ b ≤ 1 0 10001 1 \leq b \leq 10^{10001} 1≤b≤1010001,且 a , b a, b a,b 不同时是 19260817 19260817 19260817 的倍数。
思路
- 首先,这个首先读入就是个麻烦事情,我们可以在读入的时候先求模,肯定不会对结果造成影响。
- 其次,这道题要求 b x ≡ a ( m o d 19260817 ) bx\equiv a\pmod{19260817} bx≡a(mod19260817),这个我们可以转化成 b x + 19260817 y = a bx+19260817y=a bx+19260817y=a其中 g c d ( b , 19260817 ) = 1 gcd(b,19260817)=1 gcd(b,19260817)=1,如果不等于,则无解。
- 最后,剩下的都是扩展欧几里得的内容了(说实话,因为19260817是素数,这道题还可以用费马定理(求乘法逆元的))。
代码
//可以在读入的时候%mod
#include<iostream>
using namespace std;
const int mod = 19260817;
typedef long long LL;
LL a,b;
LL getint(){
string aa;
cin>>aa;
LL ans=0;
for(int i=0;i<aa.size();i++){
LL t=aa[i]-'0';
ans=(ans*10+t)%mod;
}
return ans;
}
int exgcd(int a,int b,LL &x,LL &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main(){
a=getint();
b=getint();
LL x,y;
int d=exgcd(b,mod,x,y);
//bx-mody=a
if(a%d){
puts("Angry!");
return 0;
}
x*=a/d;
int t=mod/d;
cout<<(x%t+t)%t;
return 0;
}