POJ 1166 高斯消元 疑惑的思考

27 篇文章 0 订阅
4 篇文章 0 订阅

不知道为什么消元的时候没选择绝对值最大的那一列就不会wa了

可能是刚好避开了数据吧觉得

可能刚好选择到每个a(i,i)=1 ,a(i,i)=3 (即a(i,i)=2 时就会出错)的那一行


已知p是素数时,模p剩余系里每个除0以外的元素都有唯一的逆。

模4时,由于4不是素数,所以不会有唯一的逆,比如2就没有逆

当在消元化简到 ax=b(mod 4) 我们枚举x=0,1,2,3可能都没有解

这是因为线性模方程 ax=b(mod n)  -> ax-ny=b ,  d=(a,n) ,  当 b%d!=0 时是没有解的

而当n是素数,d=(a,n)=1,b%d=0,肯定有解


事先算好这个矩阵的逆(在模4时同样可能出错)后直接乘得到结果觉得应该也可以过

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#include <vector>
#include <string>
using namespace std;
int a[9][10]={
{1,1,0,1,0,0,0,0,0,0},
{1,1,1,0,1,0,0,0,0,0},
{0,1,1,0,0,1,0,0,0,0},
{1,0,0,1,1,0,1,0,0,0},
{1,0,1,0,1,0,1,0,1,0},
{0,0,1,0,1,1,0,0,1,0},
{0,0,0,1,0,0,1,1,0,0},
{0,0,0,0,1,0,1,1,1,0},
{0,0,0,0,0,1,0,1,1,0}
};
int p=4;
int ans[100];
int gcd(int a,int b)
{
    return b==0 ? a: gcd(b,a%b);
}
int lcm(int a,int b)
{
    return a/gcd(a,b)*b;
}
int main ()
{
    for(int i=0;i<9;++i)
    {
        scanf("%d",&a[i][9]);
        a[i][9]=(4-a[i][9])%4;
    }
    int mul,ma,mb;
    for(int i=0;i<9;++i)
    {
        if(a[i][i]==0)
        {
            for(int k=i+1;k<9;++k)
                if(a[k][i])
                {
                    for(int j=0;j<=9;++j)
                        swap(a[k][j],a[i][j]);
                    break;
                }
        }
        for(int k=i+1;k<9;++k)
            if(a[k][i])
        {
            ma=a[k][i];
            mb=a[i][i];
            for(int j=i;j<=9;++j)
            {
                a[k][j]=a[k][j]*mb-a[i][j]*ma;
                a[k][j]=(a[k][j]%4+4)%4;
            }
        }
    }
    int sum=0;
    for(int i=8;i>=0;--i)
    {
        for(int k=i+1;k<9;++k)
        {
            a[i][9]-=ans[k]*a[i][k];
            a[i][9]=(a[i][9]%4+4)%4;
        }

        for(ans[i]=0;ans[i]<=3;ans[i]++)
        {
            if((a[i][i]*ans[i]%4+4)%4==a[i][9])
                break;
        }
        ans[i]%=4;
        sum+=ans[i];
    }
    int j=0,cnt=0;;
    while(j<9)
    {
        if(ans[j])
        {
            printf("%d",j+1);
            cnt++;
            if(cnt<sum)
                printf(" ");
            else printf("\n");
            ans[j]--;
        }
        else j++;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值