1. 程式人生 > 其它 >最大公約數和最小公倍數及其應用(Go語言解法)

最大公約數和最小公倍數及其應用(Go語言解法)

最大公約數(greatest common divisor)歐幾里得輾轉相除法:gcd(x,y)表示x和y的最大公約數進入運算時:x!=0,y!=0,本質上就是不斷轉換成求等價更小數的最大公約數。如果x%y=0,返回y,即最大公約數。gcd(x,y)=gcd(y,x%y)證明:設k=x/y,b=x%y 則:x=ky+b如果n能夠同時整除x和y,則(y%n)=0,(ky+b)%n=0,則b%n=0,即n也同時能夠整除y和b。由上得出:同時能夠整除y和(b=x%y)的數,也必然能夠同時整除x和y。故而gcd(x,y)=gcd(y,x%y)。當(b=x%y)=0,即y可以整除x,這時的y也就是所求的最大公約數了。附上兩條重要性質:gcd(a,b)=gcd(b,a),gcd(-a,b)=gcd(a,b)最小公倍數(least common multiple)公式解法:最小公倍數=兩數之積/最大公約數

package main

import (

"fmt"

)

/*

*窮舉法:最大公約數

*/

func gcdNormal(x, y int) int {

var n int

if x > y {

n = y

} else {

n = x

}

for i := n; i >= 1; i-- {

if x%i == 0 && y%i == 0 {

return i

}

}

return 1

}

/*

*輾轉相除法:最大公約數

*遞迴寫法,進入運算是x和y都不為0

*/

func gcd(x, y int) int {

tmp := x % y

if tmp > 0 {

return gcd(y, tmp)

} else {

return y

}

}

/*

*輾轉相除法:最大公約數

*非遞迴寫法

*/

func gcdx(x, y int) int {

var tmp int

for {

tmp = (x % y)

if tmp > 0 {

x = y

y = tmp

} else {

return y

}

}

}

/*

*窮舉寫法:最小公倍數

*/

func lcmNormal(x, y int) int {

var top int = x * y

var i = x

if x < y {

i = y

}

for ; i <= top; i++ {

if i%x == 0 && i%y == 0 {

return i

}

}

return top

}

/*

*公式解法:最小公倍數=兩數之積/最大公約數

*/

func lcm(x, y int) int {

return x * y / gcd(x, y)

}

func main() {

x, y := 12, 15

fmt.Println("gcdNormal=", gcdNormal(x, y))

fmt.Println("gcd=", gcd(x, y))

fmt.Println("gcdx=", gcdx(x, y))

fmt.Println("nlcmNormal=", lcmNormal(x, y))

fmt.Println("lcm=", lcm(x, y))

}

複製程式碼

猜生日問題:

小明對生日十分看重,因為他可以得到祝福,可以和朋友親人一起分享快樂,可以為自己的人生做一次總結,並且...能夠收到好多禮物!

不過小明是個神祕的人,不會輕易告訴你他的生日,現在他想到一個辦法,讓你去猜他的生日是哪一天。

小明會告訴你如下三個資訊:

1. 出生月份和出生日子的最大公約數;

2. 出生月份和出生日子的最小公倍數;

3. 出生年份;

現在要求你猜出小明的生日。

Input

第一行輸入一個正整數T,表示總共有T組冊數資料(T <= 200);

對於每組資料依次輸入三個數x,y,z,

x表示出生月份和出生日子的最大公約數(1<= x <=1000);

y表示出生月份和出生日子的最小公倍數(1<= y <=1000);

z表示出生年份(1900 <= z <= 2013)。

每組輸入資料佔一行。

Output

package main



import (

        "fmt"

)



/*

*窮舉法:最大公約數

*/

func gcdNormal(x, y int) int {

        var n int

        if x > y {

                n = y

        } else {

                n = x

        }

        for i := n; i >= 1; i-- {

                if x%i == 0 && y%i == 0 {

                        return i

                }

        }

        return 1

}



/*

*輾轉相除法:最大公約數

*遞迴寫法,進入運算是x和y都不為0

*/

func gcd(x, y int) int {

        tmp := x % y

        if tmp > 0 {

                return gcd(y, tmp)

        } else {

                return y

        }

}



/*

*輾轉相除法:最大公約數

*非遞迴寫法

*/

func gcdx(x, y int) int {

        var tmp int

        for {

                tmp = (x % y)

                if tmp > 0 {

                        x = y

                        y = tmp

                } else {

                        return y

                }

        }

}



/*

*窮舉寫法:最小公倍數

*/

func lcmNormal(x, y int) int {

        var top int = x * y

        var i = x

        if x < y {

                i = y

        }

        for ; i <= top; i++ {

                if i%x == 0 && i%y == 0 {

                        return i

                }

        }

        return top

}



/*

*公式解法:最小公倍數=兩數之積/最大公約數

*/

func lcm(x, y int) int {

        return x * y / gcd(x, y)

}



func main() {

        x, y := 12, 15

        fmt.Println("gcdNormal=", gcdNormal(x, y))

        fmt.Println("gcd=", gcd(x, y))

        fmt.Println("gcdx=", gcdx(x, y))

        fmt.Println("nlcmNormal=", lcmNormal(x, y))

        fmt.Println("lcm=", lcm(x, y))

}

複製程式碼 猜生日問題: 小明對生日十分看重,因為他可以得到祝福,可以和朋友親人一起分享快樂,可以為自己的人生做一次總結,並且...能夠收到好多禮物! 不過小明是個神祕的人,不會輕易告訴你他的生日,現在他想到一個辦法,讓你去猜他的生日是哪一天。 小明會告訴你如下三個資訊: 1. 出生月份和出生日子的最大公約數; 2. 出生月份和出生日子的最小公倍數; 3. 出生年份; 現在要求你猜出小明的生日。 Input 第一行輸入一個正整數T,表示總共有T組冊數資料(T <= 200); 對於每組資料依次輸入三個數x,y,z, x表示出生月份和出生日子的最大公約數(1<= x <=1000); y表示出生月份和出生日子的最小公倍數(1<= y <=1000); z表示出生年份(1900 <= z <= 2013)。 每組輸入資料佔一行。 Output 對於每組資料,先輸出Case數。 如果答案不存在 ,輸出“-1”; 如果答案存在但不唯一 ,輸出“1”; 如果答案唯一,輸出生日,日期格式為YYYY/MM/DD; 直接給出Go語言實現程式碼(為便於測試輸入問題已忽略)

package main



import (

        "fmt"

)



/*檢查如期是否合法*/

func checkDate(y, m, d int) int {

        var arr [13]int = [13]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

        //閏年

        if (y%4 == 0 && y%100 != 0) || y%400 == 0 {

                arr[2] = 29

        }

        if arr[m] < d {

                return 0

        }

        return 1

}



/*

*已知x和y的最小公倍數min和最大公約數max,求x和y

*由最小公倍數性質:min=x*y/max,所以x*y=max*min

*由最大公約數性質:x和y都可以寫成max*n

*/

func rgcd(min, max, y int, m, d *int) int {

        var mMax, dMax, res, count, tmp int = 12 / max, 31 / max, min * max, 0, 0

        for i := 1; i <= mMax; i++ {

                for j := 1; j <= dMax; j++ {

                        tmp = max * i * max * j

                        if tmp > res {

                                break

                        } else if tmp == res {

                                //計算得到的日期的合法,才加上

                                tmpM := max * i

                                tmpD := max * j

                                if checkDate(y, tmpM, tmpD) == 1 {

                                        *m = tmpM

                                        *d = tmpD

                                        //fmt.Println(*m, *d)

                                        count++

                                }

                        }

                }

        }

        if count > 1 {

                return 1

        } else if count == 1 {

                return 0

        } else {

                return -1

        }

}



func main() {

        min, max, y, m, d := 24, 3, 1999, 0, 0



        fr := rgcd(min, max, y, &m, &d)



        if fr == 0 {

                fmt.Printf("%d/%02d/%02d", y, m, d)

        } else {

                fmt.Println(fr)

        }

}

複製程式碼最小公倍數, 公約數