算法总结之求解模线性方程组

算法总结之求解模线性方程组

1)求解模线性方程 ax = b(mod n)

  方程ax = b(mod n) -> ax = b + ny ->ax - ny = b

  -> ax + n (-y) =b 其中a,n,b已知。 可用扩展欧几里得来求解该方程的一组特解。

  这里给出下列几个定理用来求解方程:

  1.当且仅当d|b时,方程ax = b(mod n)有解。d=gcd(a,n)

  2.ax = b(mod n) 或者有d个不同解,或者无解。

  3.令d=gcd(a,n) 假定对整数x', y', 有d = ax' + ny', 如果d | b, 则方程ax = b(mod n)有一个解的值为x0, 满足:

    x0=x‘(b/d)(mod n)

  4.假设方程ax = b(mod n)有解, x0是方程的任意一个解, 则方程对模n恰有d个不同的解, 分别为:

    xi = x0 + i * (n / d), 其中 i = 1,2,3......d - 1

  根据这4个定理,运用扩展欧几里得算法就能轻易的求出模线性方程的所有解了。

伪代码如下:

 

1 MODULAR_LINEAR_EQUATION_SOLVER(a,b,n)
2 (d,x',y')=EXTENDED_EUCLID(a,n)
3 if (d|b)
4     x0=x'(b/d) mod n
5     for i=0 to d-1
6     print (x0+i(n/d)) mod n
7 else
8     print "no solutions"

 

2)求解模线性方程组

  x = a1(mod m1)

  x = a2(mod m2)

  x = a3(mod m3)

  

  先求解方程组前两项。 x=m1*k1+a1=m2*k2+a2

 -> m1*k1+m2*(-k2)=a2-a1

  这个方程可以通过欧几里得求解出最小正整数的k1 则x=m1*k1+a1 显然x为两个方程的最小正整数解。

  则这两个方程的通解为 X=x+k*LCM(m1,m2) -> X=x(mod LCM(m1,m2)) 就转换成了一个形式相同方程了

  在通过这个方程和后面的其他方程求解。最终的结果就出来了。

  以POJ2891为例 贴上代码:

Code:

 1 /*************************************************************************
 2     > File Name: poj2891.cpp
 3     > Author: Enumz
 4     > Mail: 369372123@qq.com
 5     > Created Time: 2014年10月28日 星期二 02时50分07秒
 6  ************************************************************************/
 7 
 8 #include<iostream>
 9 #include<cstdio>
10 #include<cstdlib>
11 #include<string>
12 #include<cstring>
13 #include<list>
14 #include<queue>
15 #include<stack>
16 #include<map>
17 #include<set>
18 #include<algorithm>
19 #include<cmath>
20 #include<bitset>
21 #include<climits>
22 #define MAXN 100000
23 #define LL long long
24 using namespace std;
25 LL extended_gcd(LL a,LL b,LL &x,LL &y) //返回值为gcd(a,b)
26 {
27     LL ret,tmp;
28     if (b==0)
29     {
30         x=1,y=0;
31         return a;
32     }
33     ret=extended_gcd(b,a%b,x,y);
34     tmp=x;
35     x=y;
36     y=tmp-a/b*y;
37     return ret;
38 }
39 int main()
40 {
41     LL N;
42     while (cin>>N)
43     {
44         long long a1,m1;
45         long long a2,m2;
46         cin>>a1>>m1;
47         if (N==1)
48             printf("%lld\n",m1);
49         else
50         {
51             bool flag=0;
52             for (int i=2;i<=N;i++)
53             {
54                 cin>>a2>>m2;
55                 if (flag==1) continue;
56                 long long x,y;
57                 LL ret=extended_gcd(a1,a2,x,y);
58                 if ((m2-m1)%ret!=0)
59                     flag=1;
60                 else
61                 {
62                     long long ans1=(m2-m1)/ret*x;
63                     ans1=ans1%(a2/ret);
64                     if (ans1<0) ans1+=(a2/ret);
65                     m1=ans1*a1+m1;
66                     a1=a1*a2/ret;
67                 }
68             }
69             if (!flag)
70                 cout<<m1<<endl;
71             else
72                 cout<<-1<<endl;
73         }
74     }
75     return 0;
76 }

 

转载于:https://www.cnblogs.com/Enumz/p/4063477.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LM算法是一种非线性最小二乘算法,可以用于求解线性方程组。以下是一个用Python实现LM算法求解线性方程组的示例代码: ```python import numpy as np def fun(x): return np.array([ x[0] + 2 * x[1] - 2, x[0] ** 2 + 4 * x[1] ** 2 - 4 ]) def jac(x): return np.array([ [1, 2], [2 * x[0], 8 * x[1]] ]) def LM(fun, jac, x0, max_iter=100, tol=1e-6, mu=1.0): x = x0.copy() f = fun(x) J = jac(x) A = J.T @ J + mu * np.eye(len(x)) g = J.T @ f v = np.linalg.solve(A, -g) x_new = x + v f_new = fun(x_new) rho = (np.linalg.norm(f) ** 2 - np.linalg.norm(f_new) ** 2) / (v.T @ (mu * v - g)) if rho > 0: x = x_new f = f_new J = jac(x) A = J.T @ J + mu * np.eye(len(x)) g = J.T @ f if np.linalg.norm(g) < tol: return x else: mu *= max(1 / 3, 1 - (2 * rho - 1) ** 3) else: mu *= 4 for i in range(max_iter): v = np.linalg.solve(A, -g) x_new = x + v f_new = fun(x_new) rho = (np.linalg.norm(f) ** 2 - np.linalg.norm(f_new) ** 2) / (v.T @ (mu * v - g)) if rho > 0: x = x_new f = f_new J = jac(x) A = J.T @ J + mu * np.eye(len(x)) g = J.T @ f if np.linalg.norm(g) < tol: return x else: mu *= max(1 / 3, 1 - (2 * rho - 1) ** 3) else: mu *= 4 return x x0 = np.array([1, 1]) x = LM(fun, jac, x0) print(x) ``` 这个例子中,我们要求解的非线性方程组是: $$ \begin{aligned} x_1 + 2x_2 &= 2 \\ x_1^2 + 4x_2^2 &= 4 \end{aligned} $$ 其中,$x_1$和$x_2$是未知变量。我们定义一个函数`fun`来表示这个方程组,另外还需要定义一个求导的函数`jac`。在LM算法的主函数中,我们首先需要对$x$求解$f$和$J$,然后构造矩阵$A$和向量$g$,并求解$v$。接着,我们计算$\rho$,如果$\rho$大于0,则说明$x$可以更新为$x+\Delta x$,否则需要增加$\mu$的值以控制步长。最后,我们在循环中不断迭代,直到达到最大迭代次数或者梯度的范数小于给定的容差值。最终,函数返回求解得到的$x$值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值