从Codeforces GYM 100644H:We’ve Got Chemistry, Babe 中学习高斯消元

来源:互联网 发布:用matlab求矩阵方程 编辑:程序博客网 时间:2024/06/06 01:02

这道题是裸的高斯消元,设每种物质前面的化学计量数是xi,写方程出来解就可以了

有几个注意点:

1.化学计量数的方程一定是一个不定方程组,为了保证方程组有唯一解,加一个x1=1

2.化学计量数一定要是整数,所以要用分数来表示方程的解,最后通分

   为了防止通分时最小公分母过大,最好开long long

3.可以用递归风骚的处理字符串


贴代码

#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <cmath>#include <algorithm>#include <cstdlib>#include <utility>#include <map>#include <stack>#include <set>#include <vector>#include <queue>#include <deque>#include <sstream>#define x first#define y second#define mp make_pair#define pb push_back#define LL long long#define LOWBIT(x) x & (-x)using namespace std;const int MOD=1e9+7;const int INF=0x7ffffff;const int magic=348;typedef pair<LL,LL> Pair;int ll,rr;int n=0,m;LL b[48][48];map<string,LL> ID;map<LL,LL>::iterator iter;Pair sol[48];LL res[48];inline LL gcd(LL x,LL y){if (y==0) return x; else return gcd(y,x%y);}inline LL lcm(LL x,LL y){LL res=gcd(x,y);return x/res*y;}inline LL myabs(LL x){return x>=0?x:-x;}inline void clear(int x){for (int i=1;i<=m;i++) b[x][i]=0;}inline LL getID(string el){if (ID[el]) return ID[el];ID[el]=++n;clear(n);return n;}LL readcoef(string &s){if (!isdigit(s[0])) return 1;int len=1;LL res;while (len<=s.size() && isdigit(s[len])) len++;stringstream ss(s.substr(0,len));s.erase(0,len);ss>>res;return res;}void doit(string &s,map<LL,LL> &M){if (s.size()==0) return;if (isupper(s[0])){int len=1;while (islower(s[len]) && len<=s.size()-1) len++;string el=s.substr(0,len);s.erase(0,len);LL num=getID(el);M[num]+=readcoef(s);doit(s,M);}if (s[0]=='('){s.erase(0,1);map<LL,LL> tmp;doit(s,tmp);s.erase(0,1);LL coef=readcoef(s);for (iter=tmp.begin();iter!=tmp.end();iter++) M[iter->first]+=iter->second*coef;doit(s,M);}}inline void swap(int r1,int r2){for (int i=1;i<=m;i++) swap(b[r1][i],b[r2][i]);}inline void remove(int r1,int r2,int col){if (b[r2][col]==0) return;LL lc=lcm(myabs(b[r1][col]),myabs(b[r2][col]));LL lr1=lc/b[r1][col],lr2=lc/b[r2][col];for (int i=col;i<=m;i++) b[r2][i]=lr2*b[r2][i]-lr1*b[r1][i];}Pair frac(LL x,LL y){LL g=gcd(myabs(x),myabs(y));x/=g;y/=g;if (y<0){x=-x;y=-y;}return mp(x,y);}bool solve(){int i,j,rr;for (j=1;j<=m-1;j++){rr=j;while (rr<=n && b[rr][j]==0) rr++;if (rr==n+1) return false;if (rr!=j) swap(j,rr);for (i=rr+1;i<=n;i++) remove(j,i,j);}for (i=m;i<=n;i++) if (b[i][m]!=0) return false;sol[m-1]=frac(b[m-1][m],b[m-1][m-1]);if (sol[m-1].x<=0) return false;for (i=m-2;i>=1;i--){LL lc=1,val;for (j=i+1;j<=m-1;j++)lc=lcm(lc,sol[j].y/gcd(sol[j].y,myabs(b[i][j])));for (j=i;j<=m;j++) b[i][j]*=lc;val=b[i][m];for (j=m-1;j>=i+1;j--) val-=b[i][j]/sol[j].y*sol[j].x;sol[i]=frac(val,b[i][i]);if (sol[i].x<=0) return false;}LL lc=1;for (i=1;i<=m-1;i++) lc=lcm(lc,sol[i].y);for (i=1;i<=m-1;i++) res[i]=sol[i].x*lc/sol[i].y;return true;}int main (){int i,j,mul,tot=0;string s;while (scanf("%d%d",&ll,&rr)==2 && ll && rr){m=ll+rr+1;memset(b,0,sizeof(b));n=0;ID.clear();for (i=1;i<=m-1;i++){cin>>s;map<LL,LL> M;doit(s,M);mul=i<=ll?1:-1;for (j=1;j<=n;j++) b[j][i]=mul*M[j];}clear(++n);b[n][1]=1;b[n][m]=1;printf("Case %d: ",++tot);if (!solve()){printf("No\n");continue;}for (i=1;i<=ll+rr;i++) printf("%d ",res[i]);printf("\n");}return 0;}


原创粉丝点击