noip2012同余方程 (拓展欧几里得)

来源:互联网 发布:linux test -e 编辑:程序博客网 时间:2024/06/04 18:03

题目描述

求关于 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。

NOIP 2012 提高组 第二天 第一题


noip day2 t1 的数学题(好像一直时math……………)
对于exgcd,个人感觉还是要用上几遍才能记住坑点;;

ax ≡ 1 (mod b) ———————–> ax+by=1;

所以这应该是道裸题,拓展欧几里得求解x,然后加b得到最小整数解;

对于拓展欧几里得,周围大神们的建议都是用一次推一次,绝对不背模板……
好吧,自己推一遍防止忘了;

设 ax1 +by1=gcd(a,b),bx2+(a%b)y2=gcd(b,a%b)
根据欧几里得得到gcd(a,b)==gcd(b,a%b)
ax1 +by1==bx2+(a%b)y2
然后将(a%b)展开为 a-[a/b]*b
那么得到 a*x1+b*y1=b*x2+( a - [a/b] * b ) * y2
展开右面 a*x1+b*y1=b*x2 + a*y2 - [a/b]*y2*b
合并同类项 a*x1+b*y1=a*y2 +b (x2-[a/b]*y2 )
然后得到结果 x1=y2,y1=(x2-[a/b]*y2)

然后考虑特殊情况作为递归边界
当gcd(a,b)==1时,x=1,y=0;

然后可以做到递归求解;

#include<iostream>#include<cstdio>using namespace std;int a,b,ex_x,ex_y,x,y;void exgcd(int a,int b,int &ex_x,int &ex_y,int &x,int &y){    if(b==0){a=1,x=1,y=0,ex_x=1,ex_y=0;return;}    exgcd(b,a%b,ex_x,ex_y,x,y);    ex_x=y;ex_y=x-int(a/b)*y;    x=ex_x;y=ex_y;}int main(){    scanf("%d%d",&a,&b);    exgcd(a,b,ex_x,ex_y,x,y);    while(x<0) x+=b;    printf("%d",x);    return 0;}
0 0
原创粉丝点击