题意:
求出最小的正整数 b b b,使得存在正整数 a < b a\lt b a<b,满足 a ≡ b x ( m o d p ) a\equiv bx\pmod p a≡bx(modp)
p , x p,x p,x已知,且 p p p为质数, 1 < x < p ≤ 1 0 15 1\lt x\lt p\le10^{15} 1<x<p≤1015
分析:
和解同余方程一样,把 a ≡ b x ( m o d p ) a\equiv bx\pmod p a≡bx(modp)转化为 a = b x − p y a=bx-py a=bx−py
由于
0
<
a
<
b
0\lt a\lt b
0<a<b,即
0
<
b
x
−
p
y
<
b
0\lt bx-py\lt b
0<bx−py<b,可解得:
p
x
<
b
y
<
p
x
−
1
\frac{p}{x}\lt \frac{b}{y}\lt \frac{p}{x-1}
xp<yb<x−1p
然后解最小的正整数 b b b即可,方法的话就是辗转相除法,可以看这里:传送门
(根据dls的讲解写的,可能存在纰漏,欢迎指正。)
以下代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
void solve(LL a,LL b,LL &x,LL &y,LL c,LL d)
{
//d==0说明c/d是正无穷,区间内肯定有整数
if(d==0||(c%d==0?(a/b+1<c/d):(a/b+1<=c/d)))
{ //若a/b到c/d之间有整数
x=a/b+1;
y=1;
return;
}
LL t=a/b;
a-=t*b;
c-=t*d;
solve(d,c,y,x,b,a);
x+=t*y;
}
LL qmul(LL a,LL b,LL c)
{
LL res=0;
while(b)
{
if(b&1)
res=(res+a)%c;
a=(a<<1)%c;
b>>=1;
}
return res;
}
LL p,x,b,y,a;
LL A,B,C,D;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld %lld",&p,&x);
A=p/gcd(p,x),B=x/gcd(p,x);
C=p/gcd(p,x-1),D=(x-1)/gcd(p,x-1);
solve(A,B,b,y,C,D);
a=qmul(b,x,p);
printf("%lld/%lld\n",a,b);
}
return 0;
}