专栏文章
P2613 【模板】有理数取余 讲解
P2613题解参与者 4已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @miq04e77
- 此快照首次捕获于
- 2025/12/03 20:46 3 个月前
- 此快照最后确认于
- 2025/12/03 20:46 3 个月前
声明:
在接下来的讲述中,我会用 代表题中的模数 。
前置芝士:
- 快读;
- 逆元;
- 扩展欧几里得。
正解:
-
读入:很显然,这道题输入的数太大了,根本不能用正常的方法输入,用字符串行不行呢?太麻烦了。所以我们考虑在输入时对其取模。还记得快读吗?我们只需要加一个取余就行了。如:CPP
inline int rd(){ int x=0,ch=getchar(); while(!isdigit(ch)&&ch!=EOF) ch=getchar(); while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch-'0'),x%=mod,ch=getchar(); return x; }
解决了读入,剩下的就很简单了。
首先把题目中的式子改一下,如:
将除以 改为乘 的逆元,即乘 。接下来就要看看逆元如何求了。这里我采用的是扩展欧几里得求逆元。
-
扩欧求逆元:已知求逆元时,我们会写出一个同余方程:,解出的 即为 在模 意义下的逆元。在题中,用于求解 在模 意义下的逆元的方程是:,那如何解这个方程呢?很简单,将其改造一下:由于 可以是任何数,所以可以写成:转化为熟悉的样子:求解过程:设:把 和 不断代入递归求解,直至 为 ,递归 回去求解。像这样求出来的 就是 在模 意义下的逆元了。最后用 乘 再取模就行了。
代码:
CPP#include<bits/stdc++.h>
#define inl inline
#define reg register
#define int long long
#define rep(i,x,y) for(reg int i=x;i<=(y);++i)
#define per(i,x,y) for(reg int i=x;i>=(y);--i)
using namespace std;
const int p=19260817;
inline int rd(){
int x=0,ch=getchar();
while(!isdigit(ch)&&ch!=EOF) ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch-'0'),x%=p,ch=getchar();
return x;
}
int a,b,x,y;
void exgcd(int a,int b){
if(b==0){
x=1;
y=0;
return;
}
exgcd(b,a%b);
int t=x;
x=y;
y=t-(a/b)*y;
}
signed main(){
a=rd();
b=rd();
if(b==0){ //分母不能为 0,故无解。
cout<<"Angry!";
return 0;
}
exgcd(b,p);
x=(x%p+p)%p; //保证为正数
cout<<a*x%p;
return 0;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...