P2613 【模板】有理数取余
P2613 【模板】有理数取余
题目描述
给出一个有理数 \(c=\frac{a}{b}\),求 \(c \bmod 19260817\) 的值。
这个值被定义为 \(bx\equiv a\pmod{19260817}\) 的解。
提示
对于所有数据,保证 \(0\leq a \leq 10^{10001}\),\(1 \leq b \leq 10^{10001}\),且 \(a, b\) 不同时是 \(19260817\) 的倍数。
solution:
猛然发现这么重要的题我居然没写 Solution ,第一次知道分数还能取余还是在24年上半年(大概)。然后就踏入了魔幻的模意义下的世界。
先说同余方程:
\[bx\equiv a\pmod{p}
\]
\[bx+py=a
\]
\[bx+py=gcd(b,p)=1
\]
我们将方程转化成这个形式之后求一个最小正整数解然后乘上a然后再求最下真整数解就好了。
再说费马小定理:
不难发现 \(P\) 是一个质数,由费马小定理可知:
\[b^{p-1}\equiv 1\pmod{p}
\]
\[bx'\equiv 1\pmod{p}
\]
\[x'=b^{p-2}
\]
\[x=ax'
\]
其实只要模数是一个质数的话最好还是写费马小定理吧,码量少还不容易错。
Code1:
#include<bits/stdc++.h>
#define int long long
const int mod=19260817;
using namespace std;
int x,y;
int read()
{
int res=0;char c=getchar();
while(c<48||57<c)c=getchar();
while(48<=c&&c<=57)res=((res<<3)+(res<<1)+c-'0')%mod,c=getchar();
return res;
}
void exgcd(int a,int b,int &x,int &y)
{
if(!b){x=1,y=0;return ;}
exgcd(b,a%b,y,x);y-=a/b*x;
}
void work()
{
int a,b;
a=read();
b=read();
if(b==0)
{
cout<<"Angry!";
return;
}
exgcd(b,mod,x,y);
x=(x+mod)%mod;
x=(x*a)%mod;
cout<<x;
}
#define int
int main()
{
work();
return 0;
}
Code2:
#include<bits/stdc++.h>
#define int long long
const int mod=19260817;
using namespace std;
int read()
{
int res=0;char c=getchar();
while(c<48||57<c)c=getchar();
while(48<=c&&c<=57)res=((res<<3)+(res<<1)+c-'0')%mod,c=getchar();
return res;
}
int mul(int x,int y){return x*y%mod;}
int qpow(int x,int k)
{
int res=1;
while(k)
{
if(k&1)res=mul(res,x);
x=mul(x,x);k>>=1;
}
return res;
}
void work()
{
int a=read(),b=read();
if(!b){cout<<"Angry!";return;}
b=qpow(b,mod-2);
int ans=mul(a,b)%mod;
cout<<ans;
}
#undef int
int main()
{
work();
return 0;
}

浙公网安备 33010602011771号