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;
}
posted @ 2025-02-07 18:43  liuboom  阅读(47)  评论(0)    收藏  举报