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行超爽程序!!!
看来以后做有关数学的题时要多考虑数论了。