vijos p1781——同余方程(noip2012提高组第1题)

描述

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

格式

输入格式

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

输出格式

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

样例输入1

3 10

样例输出1

7

一开始是想的直接累加b,感觉不会超时。(当时好像试了12345678和23456789,0.4秒左右就算出来了)

结果超了4组,先附上超时代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
long long a,b,ans;
int main()
{
  freopen("mod.in","r",stdin);
  freopen("mod.out","w",stdout);
  cin>>a>>b;
  if(a==1)
  {
    cout<<1;
    exit(0);
  }
  long long t=(b+1)%a;
  ans+=(b+1)/a;
  if(t%a==0)
  {
    cout<<t/a;
    exit(0);
  }
  while(1)
  {
    //while(t<a)
    t+=(a-t)/b*b;
    if(t==a)break;
    t+=b;
    ans+=t/a;
    t%=a;
    if(t==0)break;
  }
  cout<<ans;
  return 0;
}

过了很久才想起扩展欧几里得算法(题目可转化为求ax+by+1=0的x的最小正整数解)

于是乎:

#include<cstdio>
#include<iostream>
using namespace std;
int a,b,x,y;
int aa(int a,int b,int &x,int &y)
{
  if(b==0)
  {
    x=1;
    y=0;
    return a;
  }
  int ans=aa(b,a%b,x,y);
  int temp=x;
  x=y;
  y=temp-(a/b)*y;
  return ans;
}
int main()
{
  freopen("mod.in","r",stdin);
  freopen("mod.out","w",stdout);
  cin>>a>>b;
  aa(a,b,x,y);
  while(x<=0)x+=b;
  cout<<x;
}

27行超爽程序!!!

看来以后做有关数学的题时要多考虑数论了。

原文地址:https://www.cnblogs.com/937337156Zhang/p/5696970.html