NOIP提高组 2012 同余方程

来源:互联网 发布:淘宝皇冠号多少钱 编辑:程序博客网 时间:2024/06/05 05:30

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:

3 10

输出样例#1:

7

【数据范围】

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

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

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

/**************************    Name:同余方程    problem:求方程ax ≡ 1 (mod b)最小正整数解    By:Shine_Sky**************************//***************************    ax ≡ 1 (mod b)    这是我们要求的方程    我们设有一个z使得 ax = 1 + bz    也就是 ax + bz = 1是不是很像一个东西    我说的就是拓展欧几里得    要不这样换一下 ax + b*(-z) = 1    设 y = -z    则 ax + by = 1    是不是?    我们看一下拓展欧几里得方程    ax + by = gcd(a,b)    就差后面的1了    我们假设gcd(a,b)!=1;    那么存在d是a,b的公因子且大于1    且 a = dA , b = dB;    那么ax + by = 1;    则 dA * x + dB * y = 1;    d*(Ax +By) = 1;    那么d|1所以d<=1 矛盾    所以d = gcd(a,b) = 1;    就是拓欧了***************************/#include <iostream>#include <cstdio>#define f(i,a,b)    for(register int i = a;i <= b; ++ i)#define fd(i,a,b)   for(register int i = a;i >= b; -- i)using namespace std;inline int read(){    int data  =  0 , w  =  1; char ch = 0;    while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();    if(ch == '-') w = -1,ch = getchar();    while(ch >= '0' && ch <= '9') data = data * 10 + ch - '0',ch = getchar();    return data*w;}inline void write(int x){    if(x < 0) putchar('-') , x = -x;    if(x / 10) write(x / 10);    putchar(x % 10 + '0');}int a = read() , b = read() , x , y;inline void exgcd(int a , int b , int& x , int& y){    if(b == 0)    {        x = 1 , y = 0;        return;    }    exgcd(b , a % b , y , x);    y -= a / b * x;}int main(){    exgcd(a , b , x , y);    x += b;//最后x有可能小于0,但是我们要求的是最小正整数x    while(x > b)    x -= b;//优化%运算(个人习惯)    write(x);    return 0;}