http://luckycat.kshs.kh.edu.tw/homework/q10055.htm
http://uva.onlinejudge.org/external/100/10055.html
又是一題簡單題,求兩數差的絕對值有什麼難的?白癡都會!
但是,這題的難處不在這裏;注意到輸入格式了嗎?這些數不會超過2的32次方。
int只能存有限大小的整數,而這範圍是-2147483648至2147483647。
WTF!?超過了我們的秘傳口訣2147483647=2的31次方減1,代表int存不下,怎麼辦!?
沒關係,我們將傳授你如何使用更大的整數容器!
有個神秘整數型態,其可存範圍是2的63次方-1,約是1.9乘上10的19次方!
顯然2的32次方就不算什麼了,不過必須注意的是,這在C語言的標準上並沒有很明確的規定,所以在不同環境會不一樣。
同時,printf()以及scanf()的%d也只能處理到int範圍大小,超過就沒辦法了!所以也必須跟著改。
我們用很粗略的方式來區分一下。
Windows(Visual Studio以外): 宣告型態long long,輸入輸出使用%I64d
Visual Studio: 宣告型態__int64,輸出輸入使用%I64d
其它: 宣告型態long long,輸入輸出使用%lld
看不懂?沒關係,我們提供更粗略的方式:
Dev-CPP: 宣告型態long long,輸入輸出使用%I64d
UVa批改娘: 宣告型態long long,輸入輸出使用%lld
還是不清楚?沒關係,讓我們看個例子。原本int的寫法如果長這樣:
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", a+b);
在Dev-CPP上要換成:
long long ago, bgo;
scanf("%I64d%I64d", &ago, &bgo);
printf("%I64d\n", ago+bgo);
在上傳至UVa之前要換成:
long long ago, bgo;
scanf("%lld%lld", &ago, &bgo);
printf("%lld\n", ago+bgo);
在Dev-CPP上按CTRL+H就有取代功能,選擇好範圍和文字,就可以幫你全數取代了!
記不起來的話,在上面功能表 搜尋 -> 取代 也找得到。
好,這麼一來我們又學到一個新招,能對付的整數範圍上升了!
你可能會想說,有long long那我們還要int幹嘛?
當然要啊!你以為long long範圍變大不用付出任何代價嗎!?
叫碗麵加肉加蛋加麵都要錢了,買個體積暴增10個0的容器難道就不用付任何代價嗎!?
int定義上是「最適合運算的整數範圍」,所以理論上不是固定範圍,很久以前只到32767
不過現在幾乎絕版了,很難再找到有哪台機器的int範圍還在32767,可以不用擔心!
所以理論上所有整數變數型態中,運算處理最快的是int,其它都會比較慢!
而long long因為範圍大,所以相同的運算可能會花到數倍的時間!
為了效率,通常只在必要時使用long long,平常還是使用int速度快很多很多!
也許做一次加法差千萬分之一秒你沒感覺,做上幾百萬甚至幾億次時你就有感覺了!
光是一元硬幣堆個幾十萬個就很可觀了,對吧?
接下來就是怎麼找兩數差的絕對值。
絕對值的意義是,只看數值不看正負。
由於人類多半是正面積極喜歡光明的,所以傾向用正號表示單純數值大小。
也就是說,我們不希望兩數相減出現負數!這有兩種方法可以辦得到:
一、上了再說,出事再來補救!
發現減下去出現負數時,把它轉正。
二、謀定而後動,一開始就避開相減出現負數!
知道減下去會變負數,就不要真的減下去。
以一的想法來寫會是這樣:
c = a-b; <== 上就對了,後果不管它
if(c < 0) <== 完蛋中獎,趕快補救
{
c = -c; <== -c就是將c變號,當然開心的話寫-1*c或0-c也都可以!
}
以二的想法來寫會是這樣:
if(a > b) <== 先測試看看結果如何,再決定要怎麼做
{
c = a-b;
}
else
{
c = b-a;
}
通常一道題都不會只有一種解法,用不同角度看、不同想法去思考,就會得出截然不同、卻一樣能解決問題的方法!這也是它有趣的地方。
運用各種巧思,巧妙地解決問題吧!
那麼,先恭喜大家又學會了新招,並且馬上就有對象試刀!
註:本題需要會多重輸入,至EOF為止。如果你不知道什麼是EOF,或不知道如何處理多重輸入,請參考[0.0] UVa 10071。
最難的就常識 w
回覆刪除