同余方程[caioj1154]

题面描述

已知a,b,m,求x的最小正整数解,使得ax=b(mod m)
【输入格式】
一行三个整数 a,b,m。 1 ≤ a,b,m ≤ 10^9
【输出格式】
一行一个整数x,无解输出"no solution!"
【样例输入】
2 5 7
【样例输出】
6

思路

从题目的 a x = b ( m o d   m ) ax=b(mod~m) ax=b(mod m),可以转化为 a x + m y = b ax+my=b ax+my=b;
借助exgcd模版 ,我们可以直接套公式,得出特殊解x;
怎么转化为最小整数解x呢,设 d = g c d ( a , m ) d=gcd(a,m) d=gcd(a,m);
x = ( x   m o d   ( m / d ) + m / d ) )   m o d   ( m / d ) x=(x ~mod~ (m/d)+m/d))~mod~(m/d) x=(x mod (m/d)+m/d)) mod (m/d);
证明如下:
对于 a ∗ x 0 + m ∗ y 0 = b a*x_0+m*y_0=b ax0+my0=b,都有 a ∗ ( x 0 + m / d ∗ t ) + m ∗ ( y 0 − a / d ∗ t ) = b a*(x_0+m/d*t)+m*(y_0-a/d*t)=b a(x0+m/dt)+m(y0a/dt)=b.
t t t是变化次数
观察一下这个柿子, ( x 0 + m / d ∗ t ) (x_0+m/d*t) (x0+m/dt) ( y 0 − a / d ∗ t ) (y_0-a/d*t) (y0a/dt),需要满足 m / d , a / d m/d,a/d m/d,a/d均为正整数,且要求 m / d m/d m/d最小,因此, d d d应满足是 m , a m,a m,a的公约数,且要最大,就为最大公约数 g c d ( a , m ) gcd(a,m) gcd(a,m)
∴ \therefore t = 1 t=1 t=1 m / d m/d m/d x 0 x_0 x0 每次增加量的最小幅度
x = ( x   m o d   ( m / d ) + ( m / d ) )   m o d   ( m / d ) x=(x~mod~(m/d)+(m/d))~mod~(m/d) x=(x mod (m/d)+(m/d)) mod (m/d)即为最小正整数解
证毕。

代码

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define ll long long 
using namespace std;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(!b)
	{
		x=1;y=0;
		return a;
	}
	else
	{
		ll tx,ty;
		ll d=exgcd(b,a%b,tx,ty);
		x=ty;y=tx-(a/b)*ty;
		return d;
	}
}
int main()
{
	ll a,b,m,x,y;scanf("%lld%lld%lld",&a,&b,&m);
	ll d=exgcd(a,m,x,y);
	if(b%d){puts("no solution!");return 0;}
	x=x*b/d;
	y=(b-a*x)/m;
	x=(x%(m/d)+(m/d))%(m/d);
	printf("%lld\n",x);
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值