Digit Sum 시퀀스의 요소를 효율적으로 찾는 방법은 무엇입니까?


20

관심이없는 나는 프로젝트 오일러의 "최근"카테고리 ( 디지트 섬 시퀀스 ) 에서 문제를 해결하려고했습니다 . 그러나 문제를 효율적으로 해결하는 방법을 생각할 수 없습니다. 문제는 다음과 같습니다 (원래 질문 순서에는 처음에 두 가지가 있지만 순서는 변경되지 않습니다).

Digit Sum 시퀀스는 1,2,4,8,16,23,28,38,49 ....입니다. 여기서 시퀀스의 nth 항은 시퀀스 에서 앞에 오는 자릿수 입니다. 시퀀스 의 1015th 항을 찾습니다 .

순진한 솔루션은 시간이 많이 걸리므로 구현할 수 없습니다. 행렬 지수의 경우로 문제를 줄이기 위해 노력했습니다 ( O(log(1015)) 시간했지만이 순서에 대한 재발은 선형 기준에 맞는 재발을 얻을 수 없었습니다. 독특한. 시퀀스가 재발에 의해 지배되는 것을 볼 수 있습니다.

an=an1+d(an1).....(1)

여기서 은 시퀀스의 n t h 항이고 d 는 입력으로서 자연수를 주었을 때 숫자의 자릿수를 반환하는 함수입니다 (예 :annthd ). 두 번째 방법은 시퀀스에서 패턴을 찾는 것입니다. 시퀀스의 처음 몇 항은 다음과 같이 쓸 수 있음을 알 수 있습니다d(786)=21

   a_1 = 1  
   a_2 = 1 + d( 1 )
   a_3 = 1 + d( 1 ) + d( 1 + d( 1 ) )
   a_4 = 1 + d( 1 ) + d( 1 + d( 1 ) ) + d( 1 + d( 1 ) + d( 1 + d( 1 ) ) )
   a_5 = 1 + d( 1 ) + d( 1 + d( 1 ) ) + d( 1 + d( 1 ) + d( 1 + d( 1 ) ) ) + d( 1 +  d(  
   1 ) + d( 1 + d( 1 ) ) + d( 1 + d( 1 ) + d( 1 + d( 1 ) ) ) )

위 패턴 에서 시퀀스의 항은 다음 방법으로 생성 할 수 있습니다.nth

  1. 사이에 더하기 기호가있는 1을 쓰십시오 .2n1 1
  2. 제두면 다음 함수 적용 (D)를 다음에 2 개 0 다음에 다음 조건 (2 개) (1) 다음에 그리고, 조건1d2021 조건 등등.22
  3. 그런 다음 위의 방법을 각 인수에 반복적으로 적용하십시오. 적용된 d 함수의적용하십시오.d

예를 들어 n = 3이면 다음 조작을 수행합니다.

    1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
    1 + d( 1 ) + d( 1 + 1 ) + d( 1 + 1 + 1 + 1 )
    1 + d( 1 ) + d( 1 + d(1) ) + d( 1 + d( 1 ) + d( 1 +d( 1 ) ) )

동적 프로그래밍으로 I는 생성 할 수 시간에 상기 방법을 이용하여 항 O ( L를 O g ( 2 10 15 ) ) , 또 더 나은 솔루션보다 순진한된다.nthO(log(21015))

편집 1
관찰 할 수있는 또 다른 것은 입니다. 예를 들어 D ( 6 ) = D는 ( 23 ) = D는 ( 32 ) = 5 . 그러나 나는이 시점을 이용할 수 없습니다. 다시 선형 재귀 관계 (매트릭스 지수의 경우)를 찾으려고했지만 찾을 수 없습니다.d(an)=d(2n1)d(a6)=d(23)=d(32)=5

편집 2

다음은 서열이 더 작은 범위에 대해 플롯 될 때의 그래프입니다 (시퀀스의 처음 항이 플롯 됨). 106여기에 이미지 설명을 입력하십시오

추신 : Project Euler에게 솔루션을 요청하는 것은 바람직하지 않다는 것을 알고 있습니다. 그러나 나는 지난 몇 일 동안 서클에서 움직여 왔기 때문에 새로운 방향이나 힌트를 원합니다. 그것도 받아 들일 수 없다면 제안 된 경우 질문을 제거 할 수 있습니다.


1
You are given a106 = 31054319.원래 오일러 문제에서 힌트가 된 것 같습니다 .
Filip Haglund

@FilipHaglund 그건 힌트가 아닙니다. 무차별적인 힘만으로도 그 값을 쉽게 계산할 수 있습니다. 접근 방식을 확인하기위한 것입니다.
sashas

3
OEIS : oeis.org/A004207에도 있습니다.
Yuval Filmus

@EvilJS는 그래도 지그재그 방식으로 점차 증가하는 그래프를 그렸습니다. 마지막 포인트 ""캐싱 패턴 .. "을
자세히 설명해 주시겠습니까

흥미로운 패턴이 mod 9로 보이면 시퀀스 mod 11 또는 mod 99를 보면 흥미로운 일이 있습니까? mod 11 값은 홀수 인덱스 자릿수와 짝수 인덱스 자릿수의 합에서 파생 될 수 있습니다. 모드 (mod) 99는 인접 자리수의 합으로부터 도출 될 수있다.
DW

답변:


4

시퀀스는 oeis.org/A004207 에 숫자 합계로 설명되어 있습니다. mod 9 시퀀스가 ​​반복 패턴 을 갖는 것과 같은 좋은 점이 있습니다. , oeis.org/A065075oeis.org/A001370 과 디지털 루트를 공유 합니다. 이러한 특성이 유용한 경우 개방형 문제입니다 ( n - t h에 대한 닫힌 형태 방정식이 없기 때문에)(1,2,4,8,7,5)nth 수에 ).

이 시퀀스에는 언급 할 가치가있는 몇 가지 속성이
있습니다. 수 를 계산할 때 카운터 (수치 만 알고 있음)와 숫자 자체 만 저장하면됩니다. 다시 시작하려면 다음 숫자가 현재 숫자 + 숫자의 합이므로 더 이상 필요하지 않습니다.nth

처음에는 속도를 보장하기 위해 몇 가지 단계를 수행하면 값 비싼 순진 모드 및 div 계산을 피하면서 배열에 숫자를 넣는 것이 좋습니다. 이것은 일정한 속도로 속도를 높이지만 시간을 보는 것이 중요합니다.

시작점에서 다음 점을 계산할 수 있으며 다음 점까지 계산할 수 있습니다.이 점은 자릿수 변경입니다.
더 중요한 것은 패턴이 숫자가 증가함에 따라 변화하고 있다는 것입니다.
숫자 합계는 숫자 자체에 비해 작으므로 대부분의 연산에서 숫자의 일부만 변경됩니다.
그렇다면 실제로 무엇을 캐시 할 수 있습니까?

우리는 동일한 숫자의 자릿수를 가진 두 개의 숫자를 사용하면 다음 숫자를 더하는 숫자가 동일하다는 것을 알고 있습니다. 다음은 어때?

사샤

스포일러 경고, 아래는 매우 명백한 캐시 패턴입니다

달리기 에서 변하지 않는 숫자와 같은 추가 조건에 따라 시작 량으로 시작 량을 shift 라고 부릅니다 .

어떤 임의의 촬영 실행 처럼, , 및 복용 시작 에서 0 으로 9 우리가 최대 시작 지점에서 모든 패턴을 캐시 할 수 있습니다 (100) , 일부 제공하기 위해 필요한 카운터에 대처하는 방법을 알고 요소의 수를 (카운트 N을 - t의 시간10009100nth 번호)로 기억하십시오.

승인. 지금까지 모든 시작 이 다루어지면서 이상의 변화는 무엇 입니까? 당신이에서하려고하면 불행하게도이 패턴이 작동을 멈출 100 제작이 시작 동일한 일을 , 그 다음 수는 1 휴식을 완벽하게 계산하지만, 두 번째입니다. 100
1001

여기에서 우리는 포함해야 시프트 로 세트를 시작 설정 0 . 또한 다른 교대에 대한 테이블 계산을 의미 합니다 . 10

우리는 정말로 그것들을 모두 계산해야 합니까? 아니, 아니
테이블의 일부는 시작 항목 중 하나 일뿐입니다.
예를 들어 에서 시작 하면 동일한 시퀀스가 ​​이동합니다. 더 긴 캐시를 계산해야합니까? 아니요, 변경 사항 을 이동 하여 다른 실행 을 선택 하도록 계산 하므로 많은 메모리가 절약됩니다. 1,2,4,8

테이블이 적용되는 경우 이제, 우리는 초기 설정에서 시작, 테이블에서 합계를 선택 카운터를 추가하고 있음을 참조하십시오에서 우리가 얻을 수 (101) 에, 업데이트 변수와 점프 (218) 의 단계를 반복, 305 -> 406 -> 517 -> 607 -> 719- > 805- > 904- > 1003 . 승인. 지금 무엇? 11012183054065176077198059041003

시프트 가 계산 된 것보다 높을 때까지 계속할 수 있습니다 .
더 나아가서 더 많은 을 빌드 하거나 더 큰 런을 미리 계산하거나 다른 패턴을 관찰 할 수 있습니다 (예 : 이미 계산 된 테이블을 부분적으로 재사용 할 수 있음).
다른 한 번 봐 가지고 변화 와 같은 그들은 모두 같은 줄 실행 , 자리 금액에 대해 동일한 환경 인을 따라서 우리는 매우 동일한 테이블을 사용할 수 있습니다. 100 개 요소 보다 큰 테이블을 만들면 프로세스 속도가 빨라져 한 번에 더 크게 점프합니다.100,1000,10000,100000,1000000 ...
100


4

"새로운 방향이나 힌트"를 요청했는데 답을 모르겠으므로 여기에 남겨두면 도움이 되길 바랍니다. 몇 가지 아이디어 :

패턴 모드 9가있을 것입니다.

케이>1,케이10케이1모드9

귀납법으로 증명할 수 있습니다.

이것은 모든 숫자가 그들의 모드 mod 9의 합과 일치한다는 것을 의미합니다.

더욱이, 에이=(에이)모드9

에이=에이1+(에이1)=2(에이1)모드9

이 재발을 계속 확장하면

에이=2모드9

패턴 모드 9를 설명합니다.

그것은 또한 우리를 얻는다 에이=9케이+2. 반복 할 때마다 9로 나눌 수있는 차이가 발생합니다. 그 차이는 얼마나됩니까?

다음은 일반적인 코드보다 적은 것입니다.

import matplotlib.pyplot as plt
import numpy as np

#sum digits of n
def sum_digits(n):
    s = 0
    while n:
        s += n % 10
        n //= 10
    return s

#get the sequence to n digits
def calculate(n):
    retval = [1]
    for i in range(n):
        retval.append(retval[-1] + sum_digits(retval[-1]))
    return retval;

#empirically confirm that a_n = 2^n mod 9
def confirmPow2(a):
    count = 0
    for i in a[:10000]:
        if((i%9) != (2**count % 9)):
            print "false"
        count = count + 1

#find gaps divisible by 9 in a subset of a
def find9Gaps(a):
    count = 0
    S = []
    for i in a[:10000]:
         S.append(((2**count ) - i)/9)
         count = count + 1
    return S

#repeatedly sum the digits until they're less than 9...
#gives some interesting patterns
def repeatedDigitSum():
    for i in range(1000, 1100):
         print "=========for ",i
         while i > 9:
                 i = sum_digits(i)
                 print i 


a = calculate(10**6)
b = find9Gaps(a)
plt.plot(range(len(b[:100])), b[:100])
plt.show()

줄거리 (처음 100)는 지수 적으로 보이지만 완벽하다고는 생각하지 않습니다.

plot for gaps

출력은 다음과 같습니다.

>>> plt.plot(range(len(b[5:60])), np.log2(np.array(b[5:60])))
>>> plt.show()

logarithmic plot of the gaps

마지막으로 숫자의 자릿수를 합한 다음 결과 숫자의 자릿수를 합한 다음 이것을 반복하면 결국 숫자 9를 얻습니다.

10 mod 9의 거듭 제곱에 대한 위의 사실을 감안할 때 의미가 있습니다.

()(())모드9

그래도 흥미로운 일련의 숫자를 제공합니다.

편집 : 분명히 이것을 "디지털 루트"라고합니다.


1
그것은 적어도 세 번 언급되었습니다. 또한 지수 적으로 보이는 플롯을 할 때 로그를 사용해야하며 스케일 축에 대해 알려 주어야합니까? 읽을 수있는 10 ^ 16 개의 용어를 플로팅하면 정말 인상적입니다.
Evil

3 번 댓글이 달렸나요? 사람들은 "패턴 모드 9"가 있다고 말했지만 그것이 무엇인지 명확하지 않은 것처럼 느꼈습니다. 나는 이것에 대해 계속 연구 할 수 없을 것이라고 생각하기 때문에 탐험을하고 내가 가진 것을 논평했습니다. 다시 말하지만, 나는 해결책이 없지만 질문은 그것을 요구하지 않았습니다.
quietContest

EvilJS 제안에 따라 로그 플롯을 추가했습니다. numpy 나누기 때문에 더 이상 플롯 할 수 없으며
실제로이
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.