高斯消元

来源:互联网 发布:淘宝达人怎么玩 编辑:程序博客网 时间:2024/06/07 01:41

高斯消元

“其实就™是加减消元法(模拟忒麻烦)
其实我觉得 学算法最主要是对算法的理解,因为裸题在正式赛里真的很少会出….都需要你对算法进行一番魔改♂ 如果你是死搬硬背的那肯定一脸懵逼

解N元一次方程组

就和加减消元一毛一样,大概分以下几个步骤
用一个数组存下未知数的系数

1.枚举所有未知数,一个个消掉:
2.找一个系数非0的,作减数
3.算一下所有系数的最小公因数,然后把每个系数(其他项也要)乘到最小公因数
4.然后把所有式子都减去那个作减数的式子,并将那个式子标记一下,下次不能再做减数
(因为其实已经被化简掉了,如果再用来当减数那就和用一个式子化简出两个未知数带进去的后果一样)

5.到最后每一个式子肯定都被化简成了未知数=a的这种形式,求一遍答案就可以了.

如果未知数比较少,比如才三个的话(推了20分钟还少握草)就可以考虑手推公式,这样效率高而且代码短

例题

Description
现在有 a,b,c 三种物品,如果他们安 x:y:z 混合,就能产生一种神奇的物品 D 。
当然不一定只产生一份 D ,但 a,b,c 的最简比一定是 x:y:z
现在给你 3 种可供选择的物品 A,B,C :
A,B,C 都是由 a,b,c 以一定比例组合成的 , 求出最少的物品数 , 使得他们能凑出整数个 D
物品(这里的最少是指三者个数的总和最少)
Input
第一行三个整数,表示 d 的配比( x,y,z )
接下来三行,表示 A,B,C 的配比,每行三个整数( <=10000 ) 。
Output
四个整数,分别表示在 A+B+C 最 小 的前提下 A,B,C ,D 的个数
目标答案 <=10000
如果不存在满足条件的方案,输出 NONE
Sample Input
3 4 5
1 2 3
3 7 1
2 1 2
Sample Output
8 1 5 7
Data Constraint
Hint
50% 的数据保证答案中任意一个数 <=100
100% 的数据保证答案中任意一个数 <=10000

 #include <cstdio> #include <iostream> #include <cstring>using namespace std;typedef long long ll;ll cpy[3][4],f[3][4]; //[第几条式子][第几个元]ll ans[4];bool bz[4];bool isInt;int gcd(ll a,ll b){    return (b==0)?a:gcd(b,a%b);}int abs(int x) {    return (x>0)?x:-x;}int lcm(ll a,ll b) {    return (a*b/gcd(a,b));}void defact() { //这名字是我乱取的233    memset(bz,0,sizeof bz);    ll f0,l,divi;     for (int i=1; i<4; i++) { //第几个元        f0=0;        while (f[f0][i]==0 || bz[f0])  f0=f0%3+1; //找第一个系数非0的        bz[f0]=true;        l=f[f0][i];        for(int j=0; j<3; j++)             if (f[j][i]) l=lcm(l,f[j][i]); //求所有系数的lcm        for(int j=0; j<3; j++)  {            if (!f[j][i]) continue;             divi = l/f[j][i];            for (int k=0; k<4; k++) {                f[j][k]*=divi; //把整个式子全部乘上lcm/f[j][i]            }        }        for (int j=0; j<3; j++) {            if (j!=f0) {                if (!f[j][i]) continue; //如果系数已经是0了那就不用管                for (int k=0;k<4; k++) {                    f[j][k]-=f[f0][k]; //消元                }            }        }    }    for(int i=0; i<3; i++)  //找答案        for(int j=1; j<4; j++) {            if (f[i][j]!=0) {                if (f[i][0]%f[i][j]) isInt=false;                ans[j]=f[i][0]/f[i][j];                break;            }        }}int main(){    for (int i=0; i<3; i++) {        scanf("%d",&f[i][0]);    }    for (int i=0; i<3; i++) {        scanf("%d %d %d",&f[0][i+1],&f[1][i+1],&f[2][i+1]);    }    memcpy(cpy,f,sizeof f);    for (int d=1; d<=10000; d++) {        memcpy(f,cpy,sizeof cpy);        for (int i=0; i<3; i++) {            f[i][0]=f[i][0]*d;        }        isInt=true;        defact();        if (isInt && ans[1]>=0 && ans[2]>=0 && ans[3]>=0) {            cout<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<" "<<d<<endl;            return 0;        }    }    cout<<"NONE"<<endl;}

“`

1 0
原创粉丝点击