CCF CSP 201912-3 化学方程式 python满分

CCF CSP 201912-3 化学方程式(python)满分
提交截图:
在这里插入图片描述

在这里插入图片描述

样例输入:

11
H2+O2=H2O
2H2+O2=2H2O
H2+Cl2=2NaCl
H2+Cl2=2HCl
CH4+2O2=CO2+2H2O
CaCl2+2AgNO3=Ca(NO3)2+2AgCl
3Ba(OH)2+2H3PO4=6H2O+Ba3(PO4)2
3Ba(OH)2+2H3PO4=Ba3(PO4)2+6H2O
4Zn+10HNO3=4Zn(NO3)2+NH4NO3+3H2O
4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH
Cu+As=Cs+Au

输出:
N
Y
N
Y
Y
Y
Y
Y
Y
Y
N

解析:每一种原子的个数是化学式前的系数与原子后的系数相乘,因为有括号的存在,难点在于如何提取系数。
思路:计算每一个原子的个数,由外向里提取系数相乘,用一个系数列表来存储每一个原子的系数,每一个原子的初始系数为化学式前的系数。例如10HNO3,那么系数列表一共有两步,
第一步:H:10,N:10,O:10
第二步:H:10,N:10,O:30
因为O原子后面跟着数字3,则第二步的时候,O:10x3
例如:32Ba((OH)2(CO3)2)3,那么系数列表的变化为:
初始系数列表,所有元素的系数为化学式首部系数
第一步:Ba:32,O:32,H:32,C:32,O:32

先算外面的括号,乘以括号外的系数3,由于Ba不在括号内,所以Ba的系数不变
第二步:Ba:32,O:96,H:96,C:96,O:96

之后再算里面的括号外的系数,由于(OH)2在前所以先算(OH)2
第三步:Ba:32,O:192,H:192,C:96,O:96

由于OH后面的系数都为1所以直接计算(CO3)2
第四步:Ba:32,O:192,H:192,C:192,O:192

(CO3)2中,O原子后面跟着系数3,所以O元素的系数再乘3
第五步:Ba:32,O:192,H:192,C:192,O:576

计算完(CO3)2后,就没有左括号和原子了,所以系数列表就经过5步变化,之后将相同元素的个数相加即可

源码:

#====将字数型数字变为整型=================================
def Intnumber(list):#将字符型数字,变成整型
    m=len(list)
    i=0
    h=0
    while 1:
        if '0'<=list[i]<='9':
            c=list[i]
            while '0'<=list[i+1]<='9':
                h+=1
                c+=list[i+1]
                del list[i+1]
            list[i]=int(c)
        i+=1
        if i==m-1-h:
            break
    return list
#===初始化系数列表====================================
def Cftlist(x,list):#系数列表
    for i in list:
        clist.append([i,x])
    return clist
    
m = int(input())
for i in range(m):
    n = input()
    left = []
    right = []
    z1 = {}
    z2 = {}
    n_l, n_r = n.split('=')
    n_l = n_l.split('+')
    n_r = n_r.split('+')
    #=========处理化学式方程式========================================
    for t in n_l, n_r:
        z3 = {}
        for j in t:
            ls = []
            k = 0
            j = j + '-'#字符串后加一个非字母数字的符号,防止溢出
            while k <= len(j) - 2:
                if str(j[k + 1]).islower():#处理含小写字母的元素
                    ls.append(j[k] + j[k + 1])
                    z3[j[k] + j[k + 1]] = 0#将元素存于字典
                    k += 2
                else:
                    ls.append(j[k])
                    if str(j[k]).isalpha():#将化学元素存于字典
                        z3[j[k]] = 0
                    k += 1
            if t is n_l:
                left.append(ls)
                z1 = z3
            else:
                right.append(ls)
                z2 = z3
    if z1!=z2:
        print('N')
        continue
     #=========计算化学式的原子个数=============================
    clist = []
    for h in left,right:
        for v in h:
            v.append('-')#防止列表超出
            v=Intnumber(v)#字符型数字,变成整型
            x=1
            if str(v[0]).isdigit():
                x=v[0]
            clist=Cftlist(x,v)#初始化系数列表
            for k in range(len(v)):
                if str(v[k]).isalpha():#处理系数在原子后面的情况
                    if str(v[k+1]).isdigit():
                        clist[k][1] *= v[k + 1]
                a, b = 0, 0
                if v[k] == '(':#处理系数在括号外的情况
                    a += 1
                    while a > 0:
                        b += 1
                        if v[k+b] == '(':
                            a += 1
                        elif v[k+b] == ')':
                            a -= 1
                    if str(v[k+b+1]).isdigit():#括号内的元素的系数相乘
                        for t in range(k, k + b):
                            clist[t][1] *= v[k + b + 1]
            if h is left:#左边化学式的元素总数
                for t in range(len(clist)):
                    if clist[t][0] in z1:
                        z1[clist[t][0]] += clist[t][1]
            else:#右边化学式的元素总数
                for t in range(len(clist)):
                    if clist[t][0] in z2:
                        z2[clist[t][0]] += clist[t][1]
            clist=[]
        
    if z1 == z2:
        print('Y')
    else:
        print('N')
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值