main.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. func matMul(a, b []int) []int {
  8. c := make([]int, 4)
  9. c[0] = (a[0]*b[0] + a[1]*b[2]) % 1000
  10. c[1] = (a[0]*b[1] + a[1]*b[3]) % 1000
  11. c[2] = (a[2]*b[0] + a[3]*b[2]) % 1000
  12. c[3] = (a[2]*b[1] + a[3]*b[3]) % 1000
  13. return c
  14. }
  15. func estimate(scanner *bufio.Scanner) []string {
  16. caseCnt := ReadInt(scanner)
  17. answer := make([]string, caseCnt)
  18. // Conjugation is the most important clue. Assume that a = 3 + √5,
  19. // b = 3 - √5, then Xn = a^n + b^n is an integer. What's more, b^n < 1,
  20. // so Xn is the 1st number that larger than a^n.
  21. // a + b = 6, ab = 4, so a^2 - 6 + 4 = 0, b^2 - 6 + 4 = 0,
  22. // X(n+2) = 6X(n+1) - 4Xn, for | X(n+1) | _ | X(n) |
  23. // | X(n) | - B | X(n-1) |,
  24. // B is [[6, -4], [1, 0]], B^n [X(1), X(0)] = [X(n+1), X(n)]
  25. for i := 0; i < caseCnt; i++ {
  26. power := ReadInt(scanner)
  27. base := []int{6, -4, 1, 0}
  28. res := []int{1, 0, 0, 1} // E
  29. for power != 0 {
  30. if power&1 == 1 {
  31. res = matMul(res, base)
  32. }
  33. base = matMul(base, base)
  34. power /= 2
  35. }
  36. // X1 = 6, X0 = 2
  37. product := (6*res[2] + 2*res[3]) % 1000
  38. product = (product + 999) % 1000 // a^n = Xn - 1
  39. answer[i] = fmt.Sprintf("%03d", int(product))
  40. }
  41. return answer
  42. }
  43. func main() {
  44. inputFiles := []string{"C-small-practice.in", "C-large-practice.in", "test.in"}
  45. outputFiles := []string{"result-small.out", "result-large.out", "test.out"}
  46. const (
  47. small = iota
  48. large
  49. test
  50. )
  51. fileType := test
  52. fin, _ := os.Open(inputFiles[fileType])
  53. defer fin.Close()
  54. scanner := bufio.NewScanner(fin)
  55. answer := estimate(scanner)
  56. fout, _ := os.Create(outputFiles[fileType])
  57. defer fout.Close()
  58. for i, v := range answer {
  59. s := fmt.Sprintf("Case #%d: %s\n", i+1, v)
  60. fout.WriteString(s)
  61. }
  62. }