有理数求余 题解

题目描述

给出一个有理数 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} bxa(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;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈美漩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值