ABC гипотеза относится к гипотезам, когда ее формулировка понятна всем, а ее появившееся недавно доказательство непонятно никому.
Гипотеза была сформулирована независимо друг от друга математиками Дэвидом Массером в 1985 году и Джозефом Эстерле в 1988 году.
В августе 2012 года японский математик Синъити Мотидзуки заявил, что ему удалось доказать эту гипотезу.
На множестве натуральных чисел существуют две операции - сложения и умножения.
Со сложением все просто. Любое натуральное число можно представить в виде суммы единиц.
С умножением сложнее. Здесь приходится ввести понятие простого числа.
И тогда с их помощью можно получить любое натуральное число в виде произведения таких простых чисел.Основная теорема арифметики об этом как раз и говорит
Почти все известные гипотезы в теории чисел построены на том, что определяется какая-то закономерность для этих операций - сложения и умножения.
Например, гипотезы Гольдбаха (бинарная и тернарная),
гипотеза о близнецах,
гипотеза Лежандра (между n2 и n+12 всегда есть простое число),
большое количество гипотез о последовательностях, в которых встречается бесконечно много простых чисел,
Все эти гипотезы уже давным-давно сформулированы, какие-то доказаны, какие-то нет.
Каждое натуральное число n в соответствии с основной теоремой арифметики можно разложить на уникальное произведение
простых чисел:
n = p1d1 * p2d2 * ...
Введем обозначение - радикал числа n - это аналогичное разложение, в котором все простые сомножители находятся в первой степени:
rad(n) = p1 * p2 * ...
Например:
48 = 24 * 3 rad(48) = 2 * 3 = 6
Теперь рассмотрим три натуральных взаимно простых числа - A, B, C, причем A+B=C.
Рассмотрим произведение этих чисел
A*B*C
и возьмем от него радикал
rad(A*B*C)
Сразу возникает вопрос - насколько этот радикал отличается от C ? Как правило, радикал больше. Но бывает и наоборот, например:
1+8=9 > 6
5+27=32 > 30
1+48=49 > 42
32+49=81 > 42
Такие нетипичные тройки еще называются хитовыми.
Можно посчитать, что для C < 5000 таких хитовых троек будет 276
Вообще, таких хитовых троек бесконечно много при возрастании C.
Теперь возьмем квадрат радикала. Вопрос - существуют ли вообще такие тройки, для которых
C > rad(ABC)2?
Ответ на этот вопрос неизвестен. Гипотеза - не существуют. Если эта гипотеза верна, то из нее автоматически следует,
что великая теорема Ферма для n > 6.
Более того, есть другая гипотеза, что степень радикала для данного равенства не может превышать 7/4 .
Теперь сформулируем саму гипотезу ABC.
Пусть есть некое вещественное число ε > 0. Тогда существует только конечное число троек A,B,C, таких что C > rad(ABC)1+ε
Здесь ε может быть равно 0.001, 0.1, и т.д.
Для ABC можно в качестве критерия ввести параметр ρ, где
C = rad(ABC)ρ
Чем больше параметр ρ, тем хитовее считается тройка. Первой тройкой в этом списке является тройка
A=2, B=310*109, C=235, для нее ρ= 1,6299...
Вторая тройка:
A=112, B=32*56*73, C=221*23, для нее ρ=1,6260...
Третья тройка:
A=19*1307, B=7*292*318, C=28*322*54, для нее ρ=1,6235...
Вообще такие тройки можно посмотреть по ссылке тут
Рассмотрим алгоритм, который генерирует такие хитовые тройки.
Пусть n > 1. Пусть A, B, C - взаимно простые числа, причем B может быть меньше нуля.
Данный алгоритм нахождения хитовых троек основан на диофантовом уравнении (1):
Необходимым условием должно быть gcd(y, C) = 1. Это уравнение имеет решение, если выполняется условие (2):
Это равносильно тому, что
x, y, z = t, 1, z
если диофантово уравнение имеет решение для целых z.
Если
Axn ≡ Byn mod C
и
gcd(y, C) = 1
то в уравнение (2) мы можем подставить вместо t
xy-1 mod C
Для x мы можем записать
x = ty - Cu
где u - целое число.
Наc интересует нахождение решения диофантова уравнения для z=1.
Алгоритм разветвляется на две ветки - для четных n и для нечетных n.
Пусть n - четное, B < 0. Для уравнения (2) мы можем найти t, такие, что
0 < t < C
при этом отношение u/y равно отношению t/C. Тогда можно определить u из выражения
x = ty - Cu
Алгоритм получения хитовых троек основан на диофантовом уравнении.
Выбираются случайным образом малые целые коэффициенты A, B.
Тогда и радикал будет достаточно мал.
Пусть n - четное целое, больше единицы.
Также мы имеем тройку взаимно простых чисел
A>0, B<0, C>0
Находим все решения для уравнения (2) для всех t, которое лежит в диапазоне 0 < t < C.
Для каждого t:
Находим промежуточные значения:
a0 = A(ty - Cu)n
b0 = -Byn
c0 = a0 + b0
Делим a0, b0, c0 на их gcd
Вычисляем
a = min(a0, b0, c0)
c = max(a0, b0, c0)
b = c - a
Алгоритм для нечетных n похож и отличается в деталях, его описание можно найти тут.
Код
package main
import (
"math"
"math/big"
"strconv"
"fmt"
)
func factors(nn *big.Int) map[string]int64{
n := big.NewInt(0).Set(nn)
factors := make(map[string]int64)
i := big.NewInt(2)
mod := big.NewInt(0)
div := big.NewInt(0)
for {
ii := big.NewInt(0).Mul(i,i)
if ii.Cmp(n) == 1 { break }
div.DivMod(n, i, mod)
if mod.Cmp(big.NewInt(0)) > 0 {
i.Add(i, big.NewInt(1))
} else {
n.Div(n,i)
factors[big.NewInt(0).Set(i).String()] = 1
}
}
if n.Cmp(big.NewInt(1)) == 1 {
factors[n.String()] = 1
}
return factors
}
func gcd(a *big.Int, b *big.Int) *big.Int {
aa, bb, mod, div := big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0)
aa.Set(a)
bb.Set(b)
for{
if bb.Cmp(big.NewInt(0)) == 0 {break}
div.DivMod(aa, bb, mod)
aa.Set(bb)
bb.Set(mod)
}
return aa
}
func nod(a int64, b int64)(int64){
for {
if b == 0 {break}
a, b = b, a%b
}
return a
}
func rad(a map[string]int64,b map[string]int64,c map[string]int64) (*big.Int){
r := big.NewInt(1)
kk := big.NewInt(0)
for k,_ := range a{
kk.SetString(k, 0)
r.Mul(r,kk)
}
for k,_ := range b{
kk.SetString(k, 0)
r.Mul(r,kk)
}
for k,_ := range c{
kk.SetString(k, 0)
r.Mul(r,kk)
}
return r
}
func quality(a *big.Int,b *big.Int,c *big.Int) (float64){
apf := factors(a)
cpf := factors(c)
bpf := factors(b)
q := float64(0)
if len(apf) == 0 || len(cpf) == 0 || len(bpf) == 0 {
return q
}
r := rad(apf, bpf, cpf)
mlr := get_log(r)
if mlr > 0 {
q = get_log(c)
q /= mlr
}
return q
}
func get_log(n *big.Int) (z float64){
if n.Cmp(big.NewInt(1000000000)) == 1 {
l1 := len(fmt.Sprintf("%b", n)) - 1
l2 := float64(l1)*math.Log(2)
return l2
}else {
l1 := fmt.Sprintf("%d", n)
l2, _ := strconv.ParseFloat(l1, 64)
l3 := math.Log(l2)
return l3
}
}
func setABC(count int64) {
var i,j,k int64
for i=1; i < count+1; i +=1 {
for j=i+1; j < count+1; j +=1 {
for k=j+1; k < count+1; k +=1 {
if nod(i,j) == 1 && nod(i,k) == 1 && nod(j,k) == 1 {
ABC = append(ABC, i)
ABC = append(ABC, j)
ABC = append(ABC, k)
}
}
}
}
println("count=", count, "len=", len(ABC)/3)
}
func getABC(count int64) (int64,int64,int64){
var c,i,A,B,C int64
c = count*3
for i=0; i < int64(len(ABC)); i +=1 {
if i == c {
A = ABC[i]
B = ABC[i+1]
C = ABC[i+2]
break
}
}
return A,B, C
}
var ABC []int64
func main() {
ABC = make([]int64, 0)
setABC(300)
n := int64(2)
var i int64;
mod, div := big.NewInt(0), big.NewInt(0)
for i=0; i < int64(len(ABC))/3; i+=1 {
A,B,C := getABC(i)
BB := big.NewInt(B)
B *= -1
t := int64(0)
t2 := C/2
tt := make([]int64, 0)
for{
if t >= t2 {break}
div1 := big.NewInt(A)
div2 := big.NewInt(0).Exp(big.NewInt(t), big.NewInt(n), nil)
div1.Mul(div1, div2)
div.DivMod(div1, big.NewInt(C), mod)
if mod.Cmp(BB) == 0 {
tt = append(tt, t)
}
t += 1
}
if len(tt) > 0 {
ttt := make([]float64, 0)
tttu := make([]int64, 0)
for _, t := range tt{
t1 := float64(t)/float64(C)
ttt = append(ttt, t1)
ttf := int64(1)
tf := strconv.FormatFloat(t1, 'f', -10, 64)
if len(tf) < 4 {
ttf, _ = strconv.ParseInt(tf[2:3], 10, 64)
ttf *= 10
} else {
ttf, _ = strconv.ParseInt(tf[2:4], 10, 64)
}
tttu = append(tttu, ttf)
}
count := int64(0)
for _, t := range ttt{
t01 := int64(float64(t)*float64(100))
t02 := C * tttu[count]
t03 := t01 - t02
a01 := big.NewInt(t03)
a0 := big.NewInt(0).Exp(a01, big.NewInt(n), nil)
b01 := big.NewInt(-B)
b02 := big.NewInt(0).Exp(big.NewInt(100), big.NewInt(n), nil)
b0 := big.NewInt(0).Mul(b01, b02)
c0 := big.NewInt(0).Add(a0, b0)
gcd0 := gcd(a0,b0)
gcd0 = gcd(gcd0,c0)
a0.Div(a0, gcd0)
b0.Div(b0, gcd0)
c0.Div(c0, gcd0)
a := big.NewInt(0).Abs(a0)
if big.NewInt(0).Abs(b0).Cmp(a) == -1 { a = big.NewInt(0).Abs(b0)}
if big.NewInt(0).Abs(c0).Cmp(a) == -1 { a = big.NewInt(0).Abs(c0)}
c := big.NewInt(0).Abs(a0)
if big.NewInt(0).Abs(b0).Cmp(c) == 1 { c = big.NewInt(0).Abs(b0)}
if big.NewInt(0).Abs(c0).Cmp(c) == 1 { c = big.NewInt(0).Abs(c0)}
b := big.NewInt(0).Sub(c, a)
if gcd(a,b).Cmp(big.NewInt(1)) == 0 && gcd(a,c).Cmp(big.NewInt(1)) == 0 && gcd(b,c).Cmp(big.NewInt(1)) == 0 {
q := quality(a,b,c)
if q > 1.0 {
println("a=", a.String(), "b=", b.String(), "c=", c.String(), q)
}
}
}
}
}
}