P1082 [NOIP2012 提高组] 同余方程


原题链接

P1082
题目类型: 普 及 + / 提 高 {\color{lightgreen} 普及+/提高} +/
AC记录:Accepted

题目大意

求关于 x x x的同余方程 a x ≡ 1 (   m o d     b ) ax\equiv 1(\bmod\ b) ax1(mod b)的最小正整数解。

输入格式

一行,包含两个正整数 a , b a,b a,b,用一个空格隔开。

输出格式

一个正整数 x 0 x_0 x0,即最小正整数解。输入数据保证一定有解。

S a m p l e \mathbf{Sample} Sample I n p u t \mathbf{Input} Input

3 10

S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output

7

H i n t & E x p l a i n \mathbf{Hint\&Explain} Hint&Explain

数据范围

对于 40 % 40\% 40%的数据, 2 ≤ b ≤ 1 , 000 2≤b≤1,000 2b1,000
对于 60 % 60\% 60%的数据, 2 ≤ b ≤ 50 , 000 , 000 2≤b≤50,000,000 2b50,000,000
对于 100 % 100\% 100%的数据, 2 ≤ a , b ≤ 2 , 000 , 000 , 000 2\le a,b\le 2,000,000,000 2a,b2,000,000,000

解题思路

这题可以用拓展欧几里得算法(下面简称拓欧)来解决。

如果不会欧几里得算法或拓展欧几里得算法的童鞋,可以戳我

而拓欧解的方程是这样的: a x + b y = gcd ⁡ ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b),与我们的题目有很大的区别。所以我们要把题目中的同余方程变成这个样子: a x + b y = 1 ax+by=1 ax+by=1。其中的 y y y为辅助解,没什么用。又由于题目中说了:输入数据保证一定有解,所以又可以得知: gcd ⁡ ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1


解完方程以后,还有一个需要注意的点,就是题目要求的是最小正整数解,那么我们解出一个解后,如何找出其他的解呢?
答案是:设方程的一个解为 x x x,则 x + k b x+kb x+kb都是方程的解。
如果把 x + k b x+kb x+kb代入原方程,可以得到 a ( x + k b ) ≡ 1 (   m o d     b ) a(x+kb)\equiv 1(\bmod\ b) a(x+kb)1(mod b),去括号后变成 a x + k a b ≡ 1 (   m o d     b ) ax+kab\equiv 1(\bmod\ b) ax+kab1(mod b)。由于 k a b kab kab一定是 b b b的倍数,所以方程又变成了 a x ≡ 1 (   m o d     b ) ax\equiv 1(\bmod\ b) ax1(mod b),即为原方程。所以求最小正整数解就相当于把 x x x变成 ( ( x +   m o d     b ) + b )   m o d     b ((x+\bmod\ b)+b)\bmod\ b ((x+mod b)+b)mod b
注意:由于解出来的 x x x有可能是负数,所以上式在   m o d     b \bmod\ b mod b之后还要再加上一个 b b b再取模。


最后,祝大家早日
请添加图片描述

上代码

#include<iostream>

using namespace std;

int              x,y;

int exgcd(int a,int b)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    int temp=exgcd(b,a%b);
    int tx=x;
    x=y;
    y=tx-a/b*y;
    return temp;
}

int main()
{
    int a,b;
    cin>>a>>b;
    exgcd(a,b);
    // cout<<x<<" "<<y<<endl;
    x=((x%b)+b)%b;
    cout<<x<<endl;
    return 0;
}

完美切题 ∼ \sim

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值