我的想法和10樓差不多
先把 0~9 的21次方算好存起來
然后從 10的20次方開始 到 10的21次方-1 窮舉 計(jì)算 ...
pmerofc 發(fā)表于 2011-04-28 22:13
不是窮舉,是湊數(shù)。
看看每個(gè)數(shù)的差距
linux-0gt0:~ # bc
bc 1.06
Copyright 1991-1994, 1997, 199 ...
cjaizss 發(fā)表于 2011-04-28 22:37
1976年,著名的計(jì)算機(jī)大師、Pascal語言之父Niklaus Wirth提出
算法 + 數(shù)據(jù)結(jié)構(gòu) = 程序
難道C語言對待如此簡單的小學(xué)生都會(huì)做的算術(shù)問題都束手無策嗎?倒也不是這樣,辦法是有的,但需要你自己去想。編程的樂趣大抵在此。
由于本題目問題的核心在于兩個(gè)較大的數(shù)相乘超過了int類型的范圍,所以可以考慮把乘數(shù)拆成較小的數(shù)。比如
123456×654321=(123×103+456)×(654×103+321)
=123×103×(654×103+321)+ 456×(654×103+321)
=123×103×654×103+123×103×321+ 456×654×103+ 456×321
=123×654×106+123×321×103+ 456×654×103+ 456×321
=(123×654)×106+(123×321+ 456×654)×103+ 456×321
如果能分別求出(123×654)、(123×321+ 456×654)、456×321,問題不就解決了嗎?而(123×654)、(123×321+ 456×654)、456×321,可以確信,是可以用int類型表示的。
在這種情況下,用一個(gè)int變量存儲123456或654321是不行的,需要兩個(gè),一個(gè)用來記錄123456或654321的前三位,另一個(gè)記錄后三位。這種對數(shù)據(jù)的組織和安排方式,就是所謂的數(shù)據(jù)結(jié)構(gòu)。盡管這里的還只是一種很粗糙的數(shù)據(jù)結(jié)構(gòu)。此外還可以發(fā)現(xiàn),設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)首先涉及到的問題恰恰是選擇合適的數(shù)據(jù)類型。
在這種數(shù)據(jù)結(jié)構(gòu)下的算法就是:首先求出(123×654)、(123×321+ 456×654)、456×321?梢詳喽ǚe的最后三位是456×321對1000求余的結(jié)果,最前面幾位是(123×654)+(123×321+ 456×654)/103,中間三位的值為(123×321+ 456×654)%103+456×321/1000。(這些示意性的東西叫偽代碼(Pseudocode))
從對算法的描述中還可以發(fā)現(xiàn),積最好用三個(gè)int來表示。
所以,所謂的算法無非就是對操作步驟的描述。描述算法的方式有很多,其中之一就是使用自然語言來描述。用C語言描述的算法和數(shù)據(jù)結(jié)構(gòu)就是C代碼。
程序輸出
123456×654321 == 80779853376
與程序代碼3-5的輸出相比,這個(gè)結(jié)果至少可以說可信度很高,盡管我們還無法確信。
增強(qiáng)對程序正確性信心的方法只有通過測試。由于這段代碼對于兩個(gè)不多于6位的十進(jìn)制數(shù)都應(yīng)該成立,所以可以選擇易于驗(yàn)算的情況運(yùn)行程序,比如把123456改為100000再運(yùn)行程序。
然而,很遺憾,程序求100000×654321的結(jié)果竟然是
100000×654321 == 654321000
造成這個(gè)錯(cuò)誤的原因是,代碼中ji_z、ji_h表示的都是三位的十進(jìn)制數(shù),但當(dāng)它們的值為0時(shí),%d這種格式只輸出1個(gè)0而不是3個(gè)0。改進(jìn)的辦法是把它們對應(yīng)的%d改成%03d。其中3表示輸出三位,0表示如果前面有空格則填充0(可以自己上機(jī)對比一下%03d、%3d和%d之間的區(qū)別)。
把輸出改寫為
printf("%d×%d == %d%03d%03d\n" , CS1 , CS2 , ji_q , ji_z ,ji_h );
之后,可以發(fā)現(xiàn)程序求100000×654321的結(jié)果是正確的。如果還不放心,可以再找一些數(shù)據(jù)進(jìn)行測試。
回復(fù) KBTiller
兩個(gè)64位整數(shù)并做一個(gè)128位整數(shù)使用,或者使用匯編調(diào)使用bcd指令
koolcoy 發(fā)表于 2011-04-29 13:16
這個(gè)題目的算法其實(shí)不難
從根本上來說考察的是構(gòu)造數(shù)據(jù)的能力
數(shù)據(jù)組織的好,往往并不需要什么精妙的算法
KBTiller 發(fā)表于 2011-04-30 13:40
其實(shí)就是0、1、2097152……9^21的組合,要求組合的和是個(gè)21位的數(shù)字且順序符合。
先湊夠數(shù)字,就是21個(gè)數(shù)之 ...
A.com 發(fā)表于 2011-04-28 17:40
沒有9的組合不可能大于10^20
我給個(gè)思路吧。
不用去算數(shù)。
char N[21]
用循環(huán)的方式。
先計(jì)算 21 一個(gè) 1 的結(jié)果,
然后是 20 個(gè) 1 , 一個(gè) 2 ...
依次類推
...
蔡萬釗 發(fā)表于 2011-05-14 02:20
折騰啊我!!
cai@cai ~/workspace/n21cal $ time ./Debug/n21cal
1732949 種組合
the number is 12 ...
蔡萬釗 發(fā)表于 2011-05-14 06:02
我給個(gè)思路吧。
不用去算數(shù)。
char N[21]
用循環(huán)的方式。
先計(jì)算 21 一個(gè) 1 的結(jié)果,
然后是 ...
蔡萬釗 發(fā)表于 2011-05-14 02:20
128468643043731391252
449177399146038697307
請按任意鍵繼續(xù). . .
對于21位的數(shù)字,俺已經(jīng)突破1.4秒了
歡迎光臨 Chinaunix (http://www.72891.cn/) | Powered by Discuz! X3.2 |