声明:
题目来源:https://www.luogu.com.cn/problem/P1082
求关于 x x x 的同余方程 a x ≡ 1 mod b ax\equiv 1 \textrm{mod}b ax≡1modb 的最小正整数解。
输入格式
一行,包含两个正整数 a , b a,b a,b 用一个空格隔开。
输出格式
一个正整数 x 0 x_0 x0,即最小正整数解。输入数据保证一定有解。
输入输出样例
输入 #1
3 10
输出 #1
7
说明/提示
【数据范围】
对于 40 % 40 \% 40%的数据, 2 ⩽ b ⩽ 1 , 000 2 \leqslant b \leqslant 1,000 2⩽b⩽1,000。
对于 60 % 60 \% 60%的数据, 2 ⩽ b ⩽ 50 , 000 , 000 2 \leqslant b \leqslant 50,000,000 2⩽b⩽50,000,000。
对于 100 % 100 \% 100%的数据, 2 ⩽ a , b ⩽ 2 , 000 , 000 , 000 2 \leqslant a,b \leqslant 2,000,000,000 2⩽a,b⩽2,000,000,000。
NOIP 2012 提高组 第二天 第一题
分析题目,不难得出下面的式子,
a x + b y = 1 ax+by=1 ax+by=1
我们要做的就是求出x最小的正整数解。
要得到有解的条件,首先要介绍引理1:
引理1: a x + b y = 1 ax+by=1 ax+by=1有解的必要条件。
a s s u m e assume assume t h a t that that a x + b y = k ax+by=k ax+by=k
a ∣ gcd ( a , b ) a|\gcd(a,b) a∣gcd(a,b) b ∣ gcd ( a , b ) b|\gcd(a,b) b∣gcd(a,b)
⇒ a x + b y ∣ gcd ( a , b ) \Rightarrow ax+by|\gcd(a,b) ⇒ax+by∣gcd(a,b)
⇒ k ∣ gcd ( a , b ) \Rightarrow k|\gcd(a,b) ⇒k∣gcd(a,b)
s o so so k mod gcd ( a , b ) = 0 k\space\textrm{mod}\space\gcd(a,b)=0 k mod gcd(a,b)=0
⇒ gcd ( a , b ) = 1 \Rightarrow\gcd(a,b)=1 ⇒gcd(a,b)=1
引理2:模余实现方法。
a m o d b = a − b [ a b ⌋ a \bmod b=a-b\left[\frac{a}{b}\right\rfloor amodb=a−b[ba⌋
例如: 13 m o d 7 = 13 − 7 [ 13 7 ⌋ = 6 13 \bmod 7=13-7\left[\frac{13}{7}\right\rfloor=6 13mod7=13−7[713⌋=6
其原理可以总结为 a a a 减去 a a a中含有的最多的 b b b ,减到不能再减为止。
a x + b y = gcd ( a , b ) = 1 a x+b y=\operatorname{gcd}(a, b)=1 ax+by=gcd(a,b)=1
b x ′ + ( a m o d b ) y ′ = gcd ( a , b ) = 1 b x^{\prime}+(a \bmod b) y^{\prime}=\operatorname{gcd}(a, b)=1 bx′+(amodb)y′=gcd(a,b)=1
a x + b y = b x ′ + ( a m o d b ) y ′ a x+b y=b x^{\prime}+(a \bmod b) y^{\prime} ax+by=bx′+(amodb)y′
= b x ′ + a y ′ − b [ a b ⌋ y ′ =b x^{\prime}+a y^{\prime}-b\left[\frac{a}{b}\right\rfloor y^{\prime} =bx′+ay′−b[ba⌋y′
= a ( y ′ ) + b ( x ′ − ⌊ a b ⌋ y ′ ) =a\left(y^{\prime}\right)+b\left(x^{\prime}-\left\lfloor\frac{a}{b}\right\rfloor y^{\prime}\right) =a(y′)+b(x′−⌊ba⌋y′)
x ≐ x 1 , y ≐ y 1 , a ≐ a 1 , b ≐ b 1 x \doteq x_{1}, y \doteq y_{1}, a \doteq a_{1}, b \doteq b_{1} x≐x1,y≐y1,a≐a1,b≐b1
y ′ ≐ x 2 , x ′ − ⌊ a b ⌋ y ′ ≐ y 2 y^{\prime} \doteq x_{2}, x^{\prime}-\left\lfloor\frac{a}{b}\right\rfloor y^{\prime} \doteq y_{2} y′≐x2,x′−⌊ba⌋y′≐y2
x n = y n + 1 , y n = x n + 1 − ⌊ a n b n ⌋ y n + 1 . x_{n}=y_{n+1}, y_{n}=x_{n+1}-\left\lfloor\frac{a_{n}}{b_{n}}\right\rfloor y_{n+1} . xn=yn+1,yn=xn+1−⌊bnan⌋yn+1.
a 2 = b 1 , b 2 = a 1 m o d b 1 a_{2}=b_{1}, b_{2}=a_{1} \bmod b_{1} a2=b1,b2=a1modb1
a n = b n − 1 , b n = a n − 1 m o d b n − 1 a_{n}=b_{n-1}, b_{n}=a_{n-1} \bmod b_{n-1} an=bn−1,bn=an−1modbn−1
a s s u m e assume assume t h a t that that f ( a , b ) = ( x , y ) f(a, b)=(x, y) f(a,b)=(x,y) m e a n s means means ( x , y ) (x, y) (x,y) s a t i s f y satisfy satisfy t h a t that that e q u a t i o n equation equation a x + b y = 1 ax+by=1 ax+by=1.
f ( a 1 , b 1 ) = ( x 1 , y 1 ) f\left(a_{1}, b_{1}\right)=\left(x_{1}, y_{1}\right) f(a1,b1)=(x1,y1)
f ( a 2 , b 2 ) = ( x 2 , y 2 ) f\left(a_{2}, b_{2}\right)=\left(x_{2}, y_{2}\right) f(a2,b2)=(x2,y2)
u n t i l until until f ( a n , b n ) = ( gcd ( a , b ) , 0 ) = ( 1 , 0 ) f\left(a_{n}, b_{n}\right)=(\operatorname{gcd}(a, b), 0)=(1,0) f(an,bn)=(gcd(a,b),0)=(1,0), c a l c u l a t e calculate calculate ( x n − 1 , y n − 1 ) \left(x_{n-1}, y_{n-1}\right) (xn−1,yn−1) r e v e r s w i s e reverswise reverswise.
f o r for for e x a m p l e example example, a = 3 , b = 10 a=3, b=10 a=3,b=10;
3 x + 10 y = 1 3 x+10 y=1 3x+10y=1;
f ( a 1 , b 1 ) = f ( 3 , 10 ) = ( x 1 , y 1 ) ; f\left(a_{1}, b_{1}\right)=f(3,10)=\left(x_{1}, y_{1}\right) ; f(a1,b1)=f(3,10)=(x1,y1);
f ( a 2 , b 2 ) = f ( 10 , 3 ) = ( x 2 , y 2 ) f\left(a_{2}, b_{2}\right)=f(10,3)=\left(x_{2}, y_{2}\right) f(a2,b2)=f(10,3)=(x2,y2)
f ( a 3 , b 3 ) = f ( 3 , 1 ) = ( x 3 , y 3 ) f\left(a_{3}, b_{3}\right)=f(3,1)=\left(x_{3}, y_{3}\right) f(a3,b3)=f(3,1)=(x3,y3)
f ( a 4 , b 4 ) = f ( 1 , 0 ) = ( x 4 , y 4 ) = ( 1 , 0 ) f\left(a_{4}, b_{4}\right)=f(1,0)=\left(x_{4}, y_{4}\right)=(1,0) f(a4,b4)=f(1,0)=(x4,y4)=(1,0)
x 1 = y 2 = x 3 − ⌊ a 2 b 2 ∣ y 3 = y 4 − ⌊ a 2 b 2 ⌋ ( x 4 − ⌊ a 3 b 3 ⌋ y 4 ) x_{1}=y_{2}=x_{3}-\left\lfloor\frac{a_{2}}{b_{2}} \mid y_{3}=y_{4}-\left\lfloor\frac{a_{2}}{b_{2}}\right\rfloor\left(x_{4}-\left\lfloor\frac{a_{3}}{b_{3}}\right\rfloor y_{4}\right)\right. x1=y2=x3−⌊b2a2∣y3=y4−⌊b2a2⌋(x4−⌊b3a3⌋y4)
= 0 − ⌊ 10 3 ⌋ ( 1 − ⌊ 3 1 ⌋ ) = − 3 ≡ 7 m o d 10 =0-\left\lfloor\frac{10}{3}\right\rfloor\left(1-\left\lfloor\frac{3}{1}\right\rfloor\right)=-3 \equiv 7 \bmod 10 =0−⌊310⌋(1−⌊13⌋)=−3≡7mod10
f o r for for e x a m p l e example example, a = 31 , b = 3731 ; a=31, b=3731 ; a=31,b=3731;
31 x + 3731 y = 1 ; 31 x+3731 y=1 ; 31x+3731y=1;
f ( a 1 , b 1 ) = f ( 31 , 3731 ) = ( x 1 , y 1 ) ; f\left(a_{1}, b_{1}\right)=f(31,3731)=\left(x_{1}, y_{1}\right) ; f(a1,b1)=f(31,3731)=(x1,y1);
f ( a 2 , b 2 ) = f ( 3731 , 31 ) = ( x 2 , y 2 ) ; f\left(a_{2}, b_{2}\right)=f(3731,31)=\left(x_{2}, y_{2}\right) ; f(a2,b2)=f(3731,31)=(x2,y2);
f ( a 3 , b 3 ) = f ( 31 , 11 ) = ( x 3 , y 3 ) ; f\left(a_{3}, b_{3}\right)=f(31,11)=\left(x_{3}, y_{3}\right) ; f(a3,b3)=f(31,11)=(x3,y3);
f ( a 4 , b 4 ) = f ( 11 , 9 ) = ( x 4 , y 4 ) ; f\left(a_{4}, b_{4}\right)=f(11,9)=\left(x_{4}, y_{4}\right) ; f(a4,b4)=f(11,9)=(x4,y4);
f ( a 5 , b 5 ) = f ( 9 , 2 ) = ( x 5 , y 5 ) ; f\left(a_{5}, b_{5}\right)=f(9,2)=\left(x_{5}, y_{5}\right) ; f(a5,b5)=f(9,2)=(x5,y5);
f ( a 6 , b 6 ) = f ( 2 , 1 ) = ( x 6 , y 6 ) ; f\left(a_{6}, b_{6}\right)=f(2,1)=\left(x_{6}, y_{6}\right) ; f(a6,b6)=f(2,1)=(x6,y6);
f ( a 7 , b 7 ) = f ( 1 , 0 ) = ( x 7 , y 7 ) = ( 1 , 0 ) f\left(a_{7}, b_{7}\right)=f(1,0)=\left(x_{7}, y_{7}\right)=(1,0) f(a7,b7)=f(1,0)=(x7,y7)=(1,0)
x 6 = y 7 = 0 ; x_{6}=y_{7}=0 ; x6=y7=0;
y 6 = x 7 − ⌊ a 6 b 6 ∣ y 7 = 1 ; y_{6}=x_{7}-\left\lfloor\frac{a_{6}}{b_{6}} \mid y_{7}=1 ;\right. y6=x7−⌊b6a6∣y7=1;
x 5 = y 6 = 1 x_{5}=y_{6}=1 x5=y6=1
y 5 = x 6 − ⌊ a 5 b 5 ⌋ y 6 = − 4 ; y_{5}=x_{6}-\left\lfloor\frac{a_{5}}{b_{5}}\right\rfloor y_{6}=-4 ; y5=x6−⌊b5a5⌋y6=−4;
x 4 = y 5 = − 4 ; x_{4}=y_{5}=-4 ; x4=y5=−4;
y 4 = x 5 − ⌊ a 4 b 4 ∣ y 5 = 5 ; y_{4}=x_{5}-\left\lfloor\frac{a_{4}}{b_{4}} \mid y_{5}=5 ;\right. y4=x5−⌊b4a4∣y5=5;
x 1 = y 2 = x 3 − ∣ a 2 b 2 ∣ y 3 = y 4 − ⌊ a 2 b 2 ∣ ( x 4 − ⌊ a 3 b 3 ∣ y 4 ) = 5 − ⌊ 3731 31 ] ( − 4 − ∣ 31 11 ∣ × 5 ) x_{1}=y_{2}=x_{3}-\left|\frac{a_{2}}{b_{2}}\right| y_{3}=y_{4}-\left\lfloor\frac{a_{2}}{b_{2}} \mid\left(x_{4}-\left\lfloor\frac{a_{3}}{b_{3}} \mid y_{4}\right)=5-\left\lfloor\frac{3731}{31}\right]\left(-4-\left|\frac{31}{11}\right| \times 5\right)\right.\right. x1=y2=x3−∣∣∣b2a2∣∣∣y3=y4−⌊b2a2∣(x4−⌊b3a3∣y4)=5−⌊313731](−4−∣∣1131∣∣×5)
= 1685 =1685 =1685
31 × 1685 m o d 3731 = 1. 31 \times 1685 \bmod 3731=1 . 31×1685mod3731=1.
代码如下:
#include
using
namespace
std;
pair<int,int> find(int a,int b){
if(a==1&&b==0) return pair<int,int>(1,0);
pair<int,int> p=find(b,a%b);
return pair<int,int>(p.second,p.first-(a/b)*p.second);
}
int refine(int a,int b){
a=a%b;
if(a<0) a+=b;
return a;
}
int main(){
int a,b;
scanf("%d%d",&a,&b);
printf("%d",refine(find(a,b).first,b));
return EOF+1;
}
引理3:欧拉函数幂的同余性质:
a s s u m e assume assume t h a t that that φ ( b ) \varphi(b) φ(b) i s is is t h e the the E u l e r ′ s Euler's Euler′s t o t i e n t totient totient f u n c t i o n function function o f of of b b b
a φ ( b ) ≡ 1 m o d b a^{\varphi(b)} \equiv 1 \bmod b aφ(b)≡1modb
通过引理3可以推得下列等式:
a x ≡ 1 m o d b a x \equiv 1 \bmod b ax≡1modb
a x ≡ a φ ( b ) m o d b a x \equiv a^{\varphi(b)} \bmod b ax≡aφ(b)modb
x ≡ a φ ( b ) − 1 m o d b x \equiv a^{\varphi(b)-1} \bmod b x≡aφ(b)−1modb
可以观察到,方程右边已经没有未知量,考虑到数据范围,只需用Euler筛法筛出 2 × 1 0 9 ⩽ 45 , 000 \sqrt{2 \times 10^{9}} \leqslant 45,000 2×109⩽45,000以内的质数,只有少于 5000 5000 5000个。
然后计算 b b b的欧拉函数即可。
代码如下:
#include
#include
#define lint unsigned long long
#define sqmaxn 45000
#define dnprime 4680
using
namespace
std;
bool isprime[sqmaxn];
lint prime[dnprime],nprime;
void Euler_mesh(){
memset(isprime,true,sizeof(isprime));
nprime=0;
for(int i=2;i<sqmaxn;i++){
if(isprime[i]){
prime[nprime]=i;
nprime++;
}
for(int j=0;i*prime[j]<sqmaxn;j++){
isprime[i*prime[j]]=false;
if(i%prime[j]==0) break;
}
}
}
lint phi(lint x){
lint ans=1;
for(int i=0;i<nprime;i++){
if(x%prime[i]==0){
x/=prime[i];
ans*=prime[i]-1;
while(x%prime[i]==0){
x/=prime[i];
ans*=prime[i];
}
}
}
return x>1?ans*(x-1):ans;
}
lint pow(lint a,lint b,lint mod){
lint ans=1,base=a;
while(b>0){
if(b&1){
ans=(ans*base)%mod;
}
base=(base*base)%mod;
b>>=1;
}
return ans;
}
signed main(){
Euler_mesh();
lint a,b;
cin>>a>>b;
cout<<pow(a,phi(b)-1,b);
return EOF+1;
}