高斯消元的应用——解模线性方程组

高斯消元想必大家应该都不陌生
对于数学中的解多元一次方程组使用的一般都是高斯消元(当年蒟蒻的我还不知道高斯消元这么low)
我们知道,对于高斯消元解普通线性方程时,
只需将方程造成一个倒三角即可
即每个方程比上一个方程少一个未知数,
然后从最后一个方程开始依次计算出每个未知数的大小
当然有些情况下,在我们消元到某一个方程时,会发现将要消去的未知数已经没了
于是我们可以在后面找到一个该未知数系数不为 0 的方程,与当前方程进行交换
当然如果在后面找不到这样一个方程,无视这个未知数将他当成0就好了
毕竟一般的解方程都是输出一组解即可
代码如下:

int a[M][M],ans[M],Id[M];
//a[1~n][1~m]代表每个方程每个未知数的系数,a[1~n][0]代表这个方程的值
//ans[1~m]代表每个未知数的解
//Id[1~n]代表每个方程解出的是哪一个未知数
void solve(){
    memset(Id,-1,sizeof(Id));
    for(int i=1,id=1;i<=n;i++){
        if(id==m+1){
            for(int j=id;j<=n;j++)
                if(a[j][0]){puts("-1");exit(0);}
                //解完后剩下的方程所有的未知数系数均为0,值确不为0,所以此时无解
            break;
        }
        bool f=0;
        while(!f&&id<=m){
            for(int j=i;j<=n;j++)
                if(a[j][id]){f=1;break;}
            if(f){
                for(int j=i;j<=n;j++)
                    if(a[j][id]){//找到第一个第id个未知数系数不为0的方程
                        for(int k=0;k<=m;k++)swap(a[i][k],a[j][k]);
                        break;
                    }
                for(int j=i+1;j<=n;j++)
                    if(a[j][id])for(int k=0,tmp=a[j][id];k<=m;k++)
                        a[j][k]=a[i][id]*a[j][k]-tmp*a[i][k];//消元,构造倒三角
                Id[i]=id;
            }
            id++;//该未知数不存在,无视之,但当前方程还存在,应用其去解下一个未知数
        }
    }
    for(int i=n;i>=1;i--){
        if(Id[i]==-1)continue;
        ans[Id[i]]=a[i][0]/a[i][Id[i]];//计算解
        for(int j=i-1;j>=1;j--)a[j][0]=a[j][0]-ans[Id[i]]*a[j][Id[i]];
    }
}

那么又怎么解模线性方程组呢
模线性方程组,顾名思义,即多个形如 (a1x1+a2x2+a3x3++anxn)%P=k 的方程组成的方程组
这种方程这么解呢,其实和普通的线性方程组没有什么区别
现在 %P 意义用上述方法得到以下 n 个式子
b1x1=k1
b2x2=k2
b3x3=k3

bnxn=kn
而后在 P 范围内枚举,找到第一个j满足 bj%P==k 即是一组解
然而这仅适用于 P 为质数的情况
由于质数与小于它的所有数都互质,所以可以这样计算
但若不是互质我们只需将其分解为n个质数,在这 %primei 都进行一次解方程
最后从小到大找到以一个满足每一个方程的数即可
代码就不给出了,只需在之前代码的基础上稍作改动即可

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值