您的位置:首页 > 其它

noip2012 同余方程

2016-08-01 17:29 246 查看

1200 同余方程

2012年NOIP全国联赛提高组

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 钻石 Diamond

题目描述 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 ≡ 1 (mod b) ax = 1 + by ax – by = 1. 其实这个方程就是让我们求a的逆.有没有解取决于gcd(a,b)是否为1.当然题目保证了有解,就不必担心,然后套用扩展欧几里得算法的模板,得出一个解x,y.这个解不一定是最小的正整数解.假设这组解为x1,y1,另外一组解为x2,y2.可以的知道ax1 + by1 = ax2 + by2 a(x1-x2) = b(y2-y1)我们同时除以gcd(a,b),可以得到x2 = (x1 + b’) y2 = (y1 – a’) 对于任意的其他解x0,y0.

X0 = (x1 + kb’),y0 = (y1 – ka’).如何得到最小解呢?对于x而言,mod一个b即可,对于y而言,mod一个a即可,但是不能保证是不是正数,这个时候加一个b’即可,因为已经是最小解了,加了一个b’一定是正数,问题就解决了.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

long long a, b, x, y;

void god(long long a, long long b, long long &x, long long &y)
{
if (!b)
{
x = 1;
y = 0;
return;
}
god(b, a%b, x, y);
int t = x;
x = y;
y = t - a / b*y;
}

int main()
{
scanf("%lld%lld", &a, &b);
god(a, b, x, y);
x = (x % b + b) % b;
printf("%lld\n", x);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: