Loading

NOIP 模拟 $18\; \rm 炼金术士的疑惑$

题解 \(by\;zj\varphi\)

高斯消元

根据高中化学知识,求解方程的就是一直方程凑出来的,焓值也一样

那么对于要求的方程和一直方程,我们做一次高斯消元,以每个物质为未知数,因为它保证有解,所以消完元后,求解方程的各项系数一定为 \(0\) 代表我们凑出这个方程了,最后答案就是求出来的值的相反数

读入时用 \(hash\)\(map\) 都行,输出时要特判 \(0.0\)

Code
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
using namespace std;
namespace IO{
    char buf[1<<21],*p1=buf,*p2=buf;
    #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
    template<typename T>inline void read(T &x) {
        ri f=1;x=0;register char ch=getchar();
        while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x=f?x:-x;
    }
}
using IO::read;
namespace nanfeng{
    #define FI FILE *IN
    #define FO FILE *OUT
    template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
    template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
    typedef double db;
    static const int N=2e3+7;
    static const db eps=1e-8;
    map<string,db> mp[N],cl;
    int n,cnt;
    db H[N],mat[N][N],tmp;
    string ts,al[N];
    inline db Gauss() {
        for (ri i(1);i<=n&&i<=cnt;p(i)) {
            int k=i;
            for (ri j(i+1);j<=n;p(j)) 
                if (fabs(mat[k][i])<fabs(mat[j][i])) k=j;
            if (k!=i) swap(mat[k],mat[i]);
            for (ri j(1);j<=n+1;p(j)) {
                if (i==j) continue;
                db tp=mat[j][i]/mat[i][i];
                for (ri l(1);l<=cnt+1;p(l)) 
                    mat[j][l]-=mat[i][l]*tp;
            }
        }
        return -mat[n+1][cnt+1];
    }//高斯约旦
    inline int main() {
        // FI=freopen("nanfeng.in","r",stdin);
        // FO=freopen("nanfeng.out","w",stdout);
        read(n);
        for (ri i(1);i<=n+1;p(i)) {
            while(1) {
                scanf("%lf",&tmp);
                cin >> ts;
                if (ts[0]=='=') break;
                if (cl.find(ts)==cl.end()) {al[p(cnt)]=ts;cl[ts]=1.0;} 
                mp[i][ts]=tmp;
                cin >> ts;
                if (ts[0]=='=') break;
            }
            while(1) {
                scanf("%lf",&tmp);
                cin >> ts;
                if (ts[0]=='H'&&ts[1]=='=') break;
                if (cl.find(ts)==cl.end()) {al[p(cnt)]=ts;cl[ts]=1.0;} 
                mp[i][ts]=-tmp;
                cin >> ts;
                if (ts[0]=='H'&&ts[1]=='=') break;
            }
            if (i<=n) scanf("%lf",&H[i]);
        }
        for (ri i(1);i<=n+1;p(i)) {
            for (ri j(1);j<=cnt;p(j)) {
                if (mp[i].find(al[j])!=mp[i].end()) 
                    mat[i][j]=mp[i][al[j]];
            }
            if (i<=n) mat[i][cnt+1]=H[i];
        }
        db ans=Gauss();
        printf("%.1lf",fabs(ans)>eps?ans:0);
        return 0;
    }  
}
int main() {return nanfeng::main();}
posted @ 2021-07-19 09:35  ナンカエデ  阅读(38)  评论(0编辑  收藏  举报