NOIP 2012 同余方程

来源:互联网 发布:淘宝怎么批量添加水印 编辑:程序博客网 时间:2024/06/05 07:38

今天机房大佬yj讲数论,正好讲到了扩欧,然后他就拿这道脱欧裸题来举例子

我想了想我还是认(hou)认(yan)真(wu)真(chi)的把这个题解发上来吧

先上题

题目描述 Description

求关于 x 同余方程 ax ≡ 1 (mod b)的最小正整数解。

输入描述 Input Description

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

输出描述 Output Description

输出只有一行包含一个正整数x0,即最小正整数解,输入数据保证一定有解。

样例输入 Sample Input

3 10

样例输出 Sample Output

7

数据范围及提示 Data Size & Hint

【数据范围】

 对于 40%  的数据, 2 ≤b≤ 1,000 ; 

对于 60% 的数据, 2 ≤b≤ 50,000,000 

对于 100% 的数据, 2 ≤a, b≤ 2,000,000,000

题目就是这样

即要求 ax % b==1的最小整数解

那么可以看到,这个跟扩欧的形式很像 转化一下可得:ax+by==1

但是这样看着还是跟扩欧有些不同 再转化:ax+by==gcd(a,b)  (a,b互质)

那这就是一个直接裸的脱欧 上代码

有什么不懂的也可以看看注释

#include<iostream>using namespace std;long long a,b,x,y,t;//将x,y定义成全局变量更方便修改/*如果不定义成全局变量也可以定义LL exgcd(LL a,LL b,LL ,x,LL y)但我这样是错误的必须要这样写LL exgcd(LL a,LL b,LL ,&x,LL &y)这样才能对他修改 所以说 还不如直接用全局变量*/void exgcd(long long a,long long b){if(b==0)//可以理解成出口之类的 找到x=1 ,y=(任意值)的特解后返回{x=1;y=0;return ;}exgcd(b,a%b);t=x;x=y;y=t-a/b*y;//这个就是扩欧 不懂的见另一篇博客return ;}int main(){cin>>a>>b;exgcd(a,b);cout<<(x+b)%b<<endl;        //为什么要+b再%b呢?        //因为如x=b 会被mod掉 x>b 则 x必能拆分b+某个值,也能被mod掉//所以x必小于b,只需+b再mod就能求出最小正整数解 }