POJ2115:利用拓展欧几里德算法求解模线性方程

我可不可以理解为中国剩余定理中n=1的情况呢?

对于C的for(i=A ; i!=B ;i +=C)循环语句,问在k位存储系统中循环几次才会结束

若在有限次内结束,则输出循环次数

否则输出死循环

设对于某组数据要循环x次结束,那么本题就很容易得到方程:

x=[(B-A+2^k)%2^k] /C

即 Cx=(B-A)(mod 2^k)  此方程为 模线性方程,本题就是求X的值

令a=C  

  b=B-A 

  n=2^k

那么原模线性方程变形为:

 ax=b (mod n)

看到这里,如果b=1,这个方程的解就被称为乘法逆元,也就是之前博文中介绍的那个

该方程有解的充要条件为 gcd(a,n) | b ,即 b% gcd(a,n)==0

(乘法逆元中b=1,这是gcd(a,n)必须是1才可以,也就是a和n必须互质,这里是一般情况)

令d=gcd(a,n)

有该方程的 最小整数解为 x = e (mod n/d)

其中e = [x0 mod(n/d) + n/d] mod (n/d) ,x0为方程的最小解

那么原题就是要计算b% gcd(a,n)是否为0,若为0则计算最小整数解,否则输出FOREVER

一般我们都是求最小整数解,不是求通解,具体的形式在程序中体现

 1 #include<cstdio>
 2 // ax=b (mod n) 
 3 long long  exgcd(long long a,long long b,long long &x,long long &y)
 4 {
 5     //扩展欧几里得算法
 6     //返回a,b的最大公约数,ax+by=gcd(a,b),x,y为方程的一组解
 7     if(b==0){x=1;y=0;return a;}
 8     long long d=exgcd(b,a%b,x,y);
 9     long long t=x;x=y;y=t-a/b*y;
10     return d;
11 }
12 long long solve(long long a,long long b,long long n)
13 {
14     long long x,y,x0;
15     long long d=exgcd(a,n,x,y);
16     if(b%d) return -1;
17     x0=(x*(b/d))%n;  //特解
18     //for(int i=1;i<d;i++)
19     //printf("%lld",x0+i*(n/d)%n); 
20     //对于不定方程,显然x0+k*b/d,y0-k*a/d,k∈Z就是所有解 
21     long long ans=x0,s=n/d;
22     ans=(ans%s+s)%s;  //最小整数解 
23     return ans; 
24 }
25 int main()
26 {
27     long long A,B,C,k;
28     while(scanf("%lld%lld%lld%lld",&A,&B,&C,&k)==4&&(A||B||C||k))
29     {
30         long long a=C;
31         long long b=B-A;
32         long long n=1LL<<k;
33         long long ans=solve(a,b,n);
34         if(ans==-1) printf("FOREVER\n");
35         else printf("%lld\n",ans);
36     }
37     return 0;
38 }

猜你喜欢

转载自www.cnblogs.com/aininot260/p/9489524.html