HeNeos blog

Josue H. @ JP Morgan Chase

HeNeos

← Back to all posts

Project Euler 346

February 10, 2024

#project-euler#algorithms#number-theory

This problem at first seems more intimidating, but it is enough to realize what are the conditions for a number to be a repunit. Then, just need to optimize by noticing what the boundaries of each base are to reduce the time complexity.

Statement

The number 77 is special, because 77 is 111111 written in base 22, and 1111 written in base 66 (i.e. 710=116=11127 _{10} = 11 _{6} = 111 _{2}). In other words, 77 is a repunit in at least two bases b>1b>1.

We shall call a positive integer with this property a strong repunit. It can be verified that there are 88 strong repunits below 5050: {1,7,13,15,21,31,40,431,7,13,15,21,31,40,43}.

Furthermore, the sum of all strong repunits below 10001000 equals 1586415864.

Find the sum of all strong repunits below 101210^{12}.

Solution

First of all, just take a look that any number n>2n > 2 can be written as 11n111 _{n-1}. It means that we only need to find another base m<n1m < n-1, where n=1111mn = 11\ldots 11 _{m}.

Now, this has already covered all the cases when the length of the repunit is 22, so the next minimum possible length for the repunit is 33:

n=111m=m2+m+1n = 111_{m} = m^{2}+m+1

Using just a raw estimation, we can say that m<nm < \sqrt{n}.

The strategy for the solution is just to iterate over all the possible bases m<nm < \sqrt{n}, and increasing the length of the repunit, then insert any visited number in a set and take the sum of elements in the set. Time complexity for the search of repunits for a base mm is just O(logm(n))O(\log_{m}(n)), so the total time complexity is just:

O(log(n)k=1n1log(k))=O(log(n)2nlog(n))=O(2n)O\bigg(\log(n) \sum_{k=1}^{\sqrt{n}} \frac{1}{\log(k)}\bigg) = O\bigg(\log(n) \frac{2\sqrt{n}}{\log(n)}\bigg) = O(2\sqrt{n})

Code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define MAXN 1000000000000
#define N 1000000

set <ll> s;

void solve(){
  for(int base=2; base<=N; base++){
    ll amount = base+1;
    for(int len=2;; len++){
      amount *= base;
      amount++;
      if(amount >= MAXN) break;
      s.insert(amount);
    }
  }
}

ll calculate_sum(){
  ll ans = 1;
  for(auto v: s) ans += v;
  return ans;
}

int main(){
  solve();
  cout << calculate_sum() << '\n';
  return 0;
}