主題 : big number ( 大數 )

28
1 主主 : Big number ( 主主 ) 主主主主 主主主主主 主主主主 主主 主主 主主 主主主主 : H.91.4 主主主主

Upload: vevina

Post on 15-Jan-2016

74 views

Category:

Documents


0 download

DESCRIPTION

主題 : Big number ( 大數 ). 解題技巧 什麼是大數? 大數運算 加法 減法 乘法 例題講解 : H.91.4 歷年題目. 什麼是大數?. 怎麼存下面的數字 100000 : int (-2 31 ~ 2 31 -1) 10000000000 : __int64 (-2 63 ~ 2 63 -1) 1000000000000000000000 : 怎麼存? 目前 C 只能用 64 bit 儲存整數, 64 bit 存不下的數字就稱為大數. 如何儲存大數. 正確評估 max_len - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 主題 : Big number ( 大數 )

1

主題 : Big number ( 大數 )

解題技巧 什麼是大數? 大數運算

加法 減法 乘法

例題講解 : H.91.4 歷年題目

Page 2: 主題 : Big number ( 大數 )

2

什麼是大數? 怎麼存下面的數字

100000 : int (-231 ~ 231-1) 10000000000 : __int64 (-263 ~ 263-1) 1000000000000000000000 : 怎麼存?

目前 C 只能用 64 bit 儲存整數, 64 bit 存不下的數字就稱為大數

Page 3: 主題 : Big number ( 大數 )

3

如何儲存大數 正確評估 max_len

最大數要多少位元 (10 進位 ) ,保證不會 overflow 5 位數 + 4 位數 <= 6 位數 5 位數 × 4 位數 <= 9 位數

用 string 來儲存 char x[max_len+1] x = “684597315274” 將每個位數用一個字元來儲存,運算時再轉換回數字

Page 4: 主題 : Big number ( 大數 )

4

如何儲存大數 用整數陣列來儲存 (for 運算,較容易 )

int num[max_len] = { 4, 7, 2, 5, 1, 3, 7, 9, 5, 4, 8, 6, 0, ..., 0}

要記得補 0

不補 0 要記有效位元長度,速度快但程式不好寫

個位數

320000000 4

500000000 6×

Page 5: 主題 : Big number ( 大數 )

5

大數運算 大數運算

加法 乘法 減法

Page 6: 主題 : Big number ( 大數 )

6

大數加法 原理

既然 C 程式內建的加法不能用,那就用最原始的加法

要注意進位的動作

4 1 7 8

4 2 5+

3

1

0

1

64

Page 7: 主題 : Big number ( 大數 )

7

資料結構 int num1[max_len], num2[max_len]

用來儲存數字

int answer[max_len] 用來儲存結果

int carry

Page 8: 主題 : Big number ( 大數 )

8

大數加法 123456789 + 987654321 ?

把 123456789 存在 num1 之中, 987654321 存在 num2 ,結果存在 answer 中

num1

num2

1 2 3 4 5 6 7 8 9

9 8 7 6 5 4 3 2 1+

111111111

111111111 0answer

0carry

0

0

Page 9: 主題 : Big number ( 大數 )

9

C code

void big_add( int *num1, int *num2, int *answer ){int i;

carry = 0; for ( i = 0 ; i < max_len ; i++) {

answer[ i] = (num1[ i] + num2[ i] + carry) % 10;carry = (num1[ i] + num2[ i] + carry) / 10;

}if (carry != 0)

printf(“Overflow!!!\n”);}

Page 10: 主題 : Big number ( 大數 )

10

10

大數乘法 原理

乘法其實就是很多個加法 注意進位和位數

4 1 7 8

4 2 5×

09804302

2

65381

21763301

1

0565771011010

Page 11: 主題 : Big number ( 大數 )

11

資料結構 num1, num2, carry 和加法一樣

中間的過程要用二維陣列來儲存? 不用,和加法一樣只需要一個一維陣列 answer 每次有新的值乘出來之後,就把它加到適當的位置去

Page 12: 主題 : Big number ( 大數 )

12

10

4 1 7 8

4 2 5×

09804302

2

65381

21763301

1

0565771011010

4 1 7 8

4 2 5×

09802

6538

0565771

054401

21761

++

+

0

00

0

0000

000

0000

000

00

00

0

Page 13: 主題 : Big number ( 大數 )

13

C code

void big_mul( int *num1, int *num2, int *answer ){int i, j; for (i = 0; i < max_len) ; i++){

carry = 0; for (j = 0; j < max_len ; j++){ if (( i + j ) < max_len) answer[i+j] = (answer[i+j] + num1[j] * num2[i] + carry) % 10;

carry= (answer[i+j] + num1[j] * num2[i] + carry) / 10; }}

}

Page 14: 主題 : Big number ( 大數 )

14

小技巧 在做大數運算時,可以將數個位數當成同一個位數來運算 之前的例子都是十進位,若換成百進位的話結果會如何?

4 1 7 8

4 2 5×

5 019

4 41 010

1 23

6 711

0565771

Page 15: 主題 : Big number ( 大數 )

15

當每一次運算所使用的位數增加時,總共所需要計算的次數就會減少,所要開的陣列大小也跟著變少

若陣列的型態為整數的話,則最多只能以萬進位為計算的單位 10000*10000 < 2^32

Page 16: 主題 : Big number ( 大數 )

16

大數減法 原理

跟加法、乘法差不多 要注意借位 可以先判斷減數或被減數大,拿大的去減小的,最後再補正負號即可

Page 17: 主題 : Big number ( 大數 )

17

大數減法 425 – 4178 = – (4178 – 425 ) = –3753

4 1 7 8

4 2 5–

35

-1

73–

Page 18: 主題 : Big number ( 大數 )

18

C code/* 假設 num1 比 num2 大 */void big_sub( int * num1, int *num2, int *answer ){int i;

carry = 0;for (i = 0; i < max_len ; i++) {answer[ i] = num1[ i] – num2[ i] + carry;if (answer[ i] < 0) {answer[ i] = answer[ i] + 10; // 若是百進位則加 100 carry = -1;}else carry = 0;}if (carry != 0)printf(“Underflow!!!\n”);

}

Page 19: 主題 : Big number ( 大數 )

19

例題講解 : H.91.4 http://www.cs.tku.edu.tw/info_race2002/codeq.htm

[a0, a1, …, an] ,其中每一個 ai 都是 0 到 9 之間的整數,而且 n 50 ( 最多有 51 個數字 )

na

aa

a

1

11

11

2

1

0

Page 20: 主題 : Big number ( 大數 )

20

Example

8

5

5

31

1

3

21

11

1

2

11

11

11

1

將連分數轉成分數

Page 21: 主題 : Big number ( 大數 )

21

Sample input/output

Sample input:

1,1,1,2

Sample

5

8

a0,a1,a2,a3

分子

分母

Page 22: 主題 : Big number ( 大數 )

22

分析

21

0 11

1

aa

a

2

210 1

11

aaa

a

1

1

21

20

aaa

a

1)1(

1

21

2210

aa

aaaa 2210

21)1(1aaaa

aa

= =

= =

Page 23: 主題 : Big number ( 大數 )

23

分析 所需的動作

乘法 加法 分子分母對調

Easy ?

Page 24: 主題 : Big number ( 大數 )

24

分析 每個 ai 最大有可能到 9 ,最多可能有

51 個 9 連乘 9^51 >> 2^63

需要大數加法和大數乘法

Page 25: 主題 : Big number ( 大數 )

25

需要的資料結構 int num[51]

儲存 a0 到 an,最多有 51 個數

int x[51] // 分子 9^51 位數最多只會有 51 位

int y[51] // 分母

Page 26: 主題 : Big number ( 大數 )

26

Program structure

intial_ 分子 _ 分母 ();

for (i = n – 1; i >= 0; i++){

count_new 分子 _new 分母 ();

}

Page 27: 主題 : Big number ( 大數 )

27

C code

int x[51], y[51], newx[51], newy[51];x[0] = 1;

y[0] = an;for (i = n – 1; i >= 0; i++){

newx y;

newy big_add ( big_mul ( y , ai) , x ) ;

/* newy = y × ai + x; */x newx;y newy;

}

這裡的大數乘法是一個大數乘以一個整數,較簡單

Page 28: 主題 : Big number ( 大數 )

28

歷年題目 練習題

A. 495 Fibonacci Freeze http://acm.uva.es/p/v4/495.html

A. 623 500! http://acm.uva.es/p/v6/623.html

A. 338 Long Multiplication http://acm.uva.es/p/v3/338.html

A. 619 Numerically Speaking http://acm.uva.es/p/v6/619.html

挑戰題 2004 兩岸清華學生程式比賽 Problem D

http://venus.cs.nthu.edu.tw/~jous/NTHU2004-Problems.doc http://venus.cs.nthu.edu.tw/~jous/pd.exe

A. 288 Arithmetic Operation with Large Integers http://acm.uva.es/p/v2/288.html

其它歷年題目 無