poj 2006 Litmus Test 【即zoj 2351:計算酸的PH】
公式: pH = -log10 [H+] PH值根據氫離子濃度求出 ,【這裏的 [H+] 濃度是摩爾每升為單位的】
Ka = [H+] [acid ions] / [acid] 平衡常數K等於分解的氫離子和酸根離子乘積與未分解的酸分子的比值
輸入格式: Ka :常數 ori :初始酸濃度 m :1摩酸分子完全溶解 分解出氫離子數 n :1摩酸分子完全溶解 分解出氫離子數【注意是完全溶解】
【這題需要特別注意的是】指數形式是可以直接輸入的。如用scanf 或者 printf要用%e輸入。
題目給出了一個比較好的例子,用了甲酸的例子:甲酸的平衡常數Ka是1.6 * 10-4,1摩爾甲酸完全溶解放出1摩爾 [H+] 和1摩爾酸根離子,如果初始濃度是0.1 moles/L,但是不知道確切有多少甲酸溶解了,設為x摩爾/L,最後平衡的時候,就有0.1 - x moles/L的甲酸分子(未溶解),[H+] 和酸根離子各 x moles/L。
注意:我上麵一直強調的兩個不同的概念,完全溶解和不完全溶解,完全溶解就是每個酸分子都水解成 [H+] 和酸根離子了,不完全溶解就是一個動態平衡的過程。我記得高中化學裏麵講到的,其實不存在完全水解的酸,就算是強電解質。。。回到題目上來,題目給出的m和n都是完全電解環境下,這樣就相當於給出了一個酸分子分解後的 [H+] 和酸根離子比例。比如m=2,n=1,就是2個 [H+] 和1個酸根離子,比如硫酸H2SO4。。。
這樣就可以設未知數列方程了,我們假設每L溶解了x摩爾的該酸,就有
Ka = mx*nx / ori-x ,變換以後就是 Ka*(ori-x) = mn*x*x ,再就是 mnx^2 + Ka*x - Ka*ori = 0,這樣就變成了一個一元二次方程,就可以開始解方程了。
x = [sqrt(Ka*Ka+4*m*n*Ka*ori)-Ka] / 2mn,這裏還沒完,因為我們隻是得到了每L溶解了x摩爾的該酸,還不是最後要求出的 [H+] ,所以還得乘上一個m。
消去分母裏麵的m,這樣才變成了大家博客裏麵津津樂道的:
i=-log10((sqrt(k*k+4*a*m*n*k)-k)/2/n); printf("%.3f\n",i);
所以,要完全弄懂還是要花一番功夫的。另外多說一句,c語言中log是以e為底的,要想以10為底,要麼除以一個log((double)10)換底,要麼見下麵的代碼。
AC代碼:
#include<stdio.h> #include<math.h> #include<iostream> using namespace std; int main() { double Ka; //平衡常數 double ori; //原始酸濃度 int m; //1摩酸分子 完全溶解 分解出氫離子數 int n; //1摩酸分子 完全溶解 分解出酸根離子數 double H; //最後計算Ph值的氫離子數 while(1) { cin>>Ka; cin>>ori; cin>>m; cin>>n; if(Ka==0&&ori==0&&m==0&&n==0) break; H=(sqrt(Ka*Ka+4*m*n*Ka*ori)-Ka)/(2*n); printf("%.3f\n",-log10(H)); } return 0; }
寫博客,我覺得我得說實話,也順便發表一個感想。
這道題目是我做ACM以來遇到的最難理解題意的一道題,對於一個高中化學一塌煳塗,又腦袋不好使的我來說還是太難了,也可能是我本身就做題太少的緣故。。但是不論怎麼說,這道題的題意理解卻是難點。。
不過,我也遇到一個很有意思的現象,網上很多人說這道題水,可我讀這道題的題目就用了個把小時,看來是我智商太低呀,不然就是我英語太差,讀不懂題目。。。但是當我看到他們粘貼的代碼很相似(其中包括一些看似大牛的人),而對這題的題目沒有一個明確分析的時候(甚至隻粘貼了一個代碼在上麵),我大概明白了是怎麼回事了。。。做ACM還是得踏實啊,裝B不能當飯吃。。。
最後更新:2017-04-03 05:39:33