Odd Tally Counter

A normal tally counter has 4 4 digits and counts 1 1 by 1 1 , hence there are 10000 10000 different numbers can be shown on it (in range 0000...9999 0000 ... 9999 ).

Suppose you have an odd tally counter. Instead 1 1 by 1 1 , it counts x x by x x . In case of overflow, the counter only shows the last 4 4 digits of the number.

For example, if x = 1001 x = 1001 the counter will show these numbers : 0000 , 1001 , 2002 , . . . , 9009 , 0010 , 1011 , . . . 0000, 1001, 2002, ..., 9009, 0010, 1011, ...

Let F ( n ) F(n) be the function returning the number of different numbers can be shown on odd tally counter with x = n x = n , find the last 3 3 digits of i = 1 9999 F ( i ) \sum_{i=1}^{9999} F(i) .

As an explicit example : F ( 1 ) = 10000 F(1) = 10000

This problem is taken from TOKI Open Contest January 2013 (Problemsetter : Me)


The answer is 90.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

13 solutions

Jiahai Feng
Dec 31, 2013

It can be shown that F ( n ) = 10000 g c d ( n , 10000 ) F(n) = \frac{10000}{gcd(n, 10000)} The gcd, or greatest common denominator can be implemented easily using the Euclidean algorithm. Simply sum F(i) from 1 to 9999, while remembering to modulo 1000 at every step.

your solution is amazing! But i'm having a hard time proving F ( n ) = 10000 g c d ( n , 10000 ) F(n)= \frac{10000}{gcd(n,10000)} , can you show me the proof ?

Renan Lordello de Aguiar - 7 years, 5 months ago

Log in to reply

I'm going to argue that F ( k ) = F ( gcd ( m , k ) ) F(k) = F(\gcd(m,k)) where we have a clock that's capable of displaying numbers up to m m without overflowing. (So in this problem, m = 1 0 4 m = 10^4 ).

Now, suppose that m m is prime (say 3 for the sake of brevity), then if x = m x = m , the only sequence it can ever generate is the constant sequence 0 0 , but if we let x x be any other number less than m m , then after enough cycles, we're going to generate every number between 0 , , m 1 0,\cdots, m-1 (proof: the sequence { k x m o d m k 1 , , m 1 } \{kx \mod m \mid k \in {1,\cdots,m-1}\} must be all disjoint because none of k x kx divides m m , and furthermore they must all be less than m m and positive; there are exactly m 1 m-1 disjoint positive number less than m m , so { k x m o d m k 1 , , m 1 } = { 1 , , m 1 } \{kx \mod m \mid k \in {1,\cdots,m-1}\} = \{1,\cdots,m-1\} ).

Next, suppose m = p a q b m = p^aq^b where both p p and q q are primes, then using the same argument as above, we can see that if x ∤ m x \not\mid m , then { k x m o d m k 0 , , m 1 } = { 0 , , m 1 } \{kx \mod m \mid k \in {0,\cdots,m-1}\} = \{0,\cdots,m-1\} ). Now, suppose that x = γ × p c q d , c < a , d < b x=\gamma \times p^cq^d, c<a,d<b , then it can only generate the sequence 0 , γ p c q d , 2 γ p c q d , , γ ( p a c q b d 1 ) p c q d , 0 , 0,\gamma p^cq^d,2\gamma p^cq^d,\cdots, \gamma(p^{a-c}q^{b-d}-1)p^cq^d, 0,\cdots , so it's length is m p c q d \frac{m}{p^cq^d} . It doesn't take much to also see that p c q d = gcd ( p a q b , γ × p c q d ) p^cq^d = \gcd(p^aq^b,\gamma \times p^cq^d) , which is why F ( k ) = F ( gcd ( m , k ) ) F(k) = F(\gcd(m,k)) .

Lee Gao - 7 years, 5 months ago

Here is another proof: Because there are finitely many combinations for the last 4 digits, at least one number must repeat. Clearly, once one number repeats, all the numbers after that number repeat. The goal is now to find the first number where they repeat.

Suppose that there were two four-digit numbers (that may start with 0), a and b, that would produce the same next number, c. In other words, a+x \equiv b+x(mod 10000). We subtract x from both sides to get a \equiv b (mod 10000). However, this means that the last 4 digits of a and b are the same. Therefore, a = b because they are both 4 digits long.

Suppose that the first number were not 0000 but some other integer m. Then we take the term before m. Because this is unique, this is the term before m both times that it repeats. This contradicts the assumption that it was the first number that repeats. However, if we take the first term that repeats to be 0000, there is no contradiction because there is no term before 0000 because that is what we started with.

We now must solve x k 0 x*k \equiv 0 (mod 10000). In other words, we must find the minimum k such that 10000 | x k x*k . In other words, we want to find the minimum k such that 10000 d = x k 10000*d=x*k for some integer d.

We rewrite x as c * gcd(x, 10000). We now want to find the minimum k such that 10000 * d=k * c * gcd(x, 10000). Because gcd(x, 10000) is a divisor of 10000, we can dividie both sides by gcd(x, 10000) and leave both sides as integers. We now have 10000 g c d ( x , 10000 d = k c \frac{10000}{gcd(x, 10000}*d=k*c . If we divide both sides by c, we get 10000 g c d ( x , 10000 d c = k \frac{10000}{gcd(x, 10000}*\frac{d}{c}=k . Therefore, d is a multiple of c. To minimize k, we let d = c. Therefore, 10000 g c d ( x , 10000 = k \frac{10000}{gcd(x, 10000}*\frac=k .

Mark Kong - 7 years ago

Whoa!!Awesome!!!Great Job!!

Eddie The Head - 7 years, 4 months ago
Shreyas Balaji
Jan 10, 2014

F ( i ) F(i) is really just the number of possible values for [ k i ( m o d 10000 ) ] \left[ki \pmod{10000} \right] for any integer k. Use the fact that the number of values possible for [ k a ( m o d n ) ] \left[ ka \pmod{n} \right] is simply ( n gcd ( a , n ) ) \left( \frac{n}{\gcd (a,n)} \right) . Thus the question becomes i = 1 9999 10000 gcd ( i , 10000 ) ) \sum_{i=1}^{9999} \frac{10000}{\gcd (i,10000))} .

Implemented in python:

from fractions import gcd
answer = sum([ (10000 / gcd(i, 10000)) for i in range(1,10000)])
print answer % 1000      # Prints last three digits => '90'
Lee Gao
Jan 1, 2014

This may take a while to brute force, so it's worth observing that F ( k ) = F ( gcd ( 1 0 4 , k ) ) F(k) = F(\gcd(10^4,k)) therefore, we can compute this problem in O ( n log ( n ) + σ ( n ) ) O(n\log(n) + \sigma(n)) time (where σ ( n ) = Θ ( n log log n ) \sigma(n) = \Theta(n\log\log n) counts the divisors of n n ) by precomputing the value of F ( d ) F(d) for all divisors of n n and then summing over F ( gcd ( n , k ) ) F(\gcd(n,k)) (which is bottlenecked in just computing the GCD, which is Θ log ( min ( n , k ) = Θ log ( k ) \Theta\log(\min(n,k) = \Theta\log(k) , therefore the running time after preprocessing is O ( k n log ( k ) = log ( n ! ) n ( log ( n ) 1 ) ) O(\sum_k^n \log(k) = \log(n!) \sim n(\log(n)-1)) ).

Furthermore, it turns out that F ( d ) = n / d F(d) = n/d , which is pretty easy to do, and it makes it so that we don't need to precompute all of the divisors beforehand! Here's the algorithm:

gcd = lambda a,b: a if b is 0 else gcd(b,a%b)
sum([10000/gcd(10000,k) for k in range(1,10000)])

which gave the sum as 55664090 55664090

i like that implementation of gcd very much , also i admire people who use lambda and comprehensions :D

Abdallah Hodieb - 7 years, 5 months ago

Log in to reply

Thanks Abdallah! I tend to like reducing all of my problems into some algebraic problem and go from there! You'll probably love functional programming: the entire paradigm builds upon the formal development of problems as an algebra

Lee Gao - 7 years, 5 months ago
Lokesh Sharma
Dec 25, 2013

Solution in Python:

def F(k):
    tally = []
    for i in range(1000):
        if (k*i)%10000 not in tally:
            tally.append((k*i)%10000)
    return len(tally)

res = 0
for i in range(1, 10000):
    res += F(i)

Nice solution, :)

Indeed, there is also a solution with Number Theory approach to solve this problem (without coding!).

Moreover, this problem has more-evil-version in https://brilliant.org/community-problem/odd-tally-counter/ .

This one is more challenging, because it requires both of Number Theory and Computer Science technique. Good luck! :D

Ammar Fathin Sabili - 7 years, 5 months ago

Log in to reply

There may still be some work to be done in the ranking system but it is interesting to note that this problem has a higher rating than the harder version.

Pedro Osório - 7 years, 5 months ago

Woop, typo : https://brilliant.org/community-problem/odd-long-tally-counter , enjoy!

Ammar Fathin Sabili - 7 years, 5 months ago

Log in to reply

Could you erase the "!" in the end? I thought it was a factorial

Mario Ynocente Castro - 7 years, 5 months ago

Log in to reply

@Mario Ynocente Castro I really want to, but I can't edit the problems myself at this time, :(

I have notified the staffs, and they will edit it, sorry for your inconvenience and a big thanks to clarify!

Ammar Fathin Sabili - 7 years, 5 months ago

Trying hard to solve the more evil version of this problem. Could you give a hint on how to use number theory?

Lokesh Sharma - 7 years, 5 months ago

Log in to reply

Hint : You have to find the simpler formula of F ( n ) F(n) which its complexity is close to O ( 1 ) O(1) . Happy solving!

Ammar Fathin Sabili - 7 years, 5 months ago

Log in to reply

@Ammar Fathin Sabili lol, I did it.... I am so happy right now!

Lokesh Sharma - 7 years, 5 months ago

@Ammar Fathin Sabili =MOD(14(4^k-1)+500(k-1)+20,1000) for tally counter with k digits

=090 for k=4

Antonio Valente Macarilay - 7 years, 4 months ago

I used This code : """def four(x) : a = str(x) if len(a) > 4 : b = "" for i in range(4): b += a[i] b = int(b) return b else : return x

def od(x) : c = 0 b = [0] d = 0 for i in range(9999) : d += x d = four(d)

    e = 0
    for i in b :
        if d == i :
            e += 1
    if e == 0 :
        b.append(d)

f = len(b)
return f

n = 0 for i in range (1 ,10000) : n += od(i) print n""" tell me what is wrong

Nikhil Tyagi - 7 years, 5 months ago

may i give u a little advice , not related to this particular problem , but consider each time you call the line " ( k*i) %10000 not in tally" all the list is searched to look for the item your looking for . the cost of searching in lists is O(n) . while if you simply changed tally from a list to a set you will gain a lot, because the cost of the search in sets is O (1) .

though this won't be noticeable in this small data set.

Abdallah Hodieb - 7 years, 5 months ago

I used a dict instead of a list as being a hash table it helps to pick out the elements in constant time...

Eddie The Head - 7 years, 4 months ago
Arjen Vreugdenhil
Nov 18, 2015

My solution is slightly longer than y'all's fancy gcd algorithms, BUT it may well be faster...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int total = 0;

for (int i = 1; i <= 9999; i++) {
    int n = i, F = 10000;
    while (n % 5 == 0 && F % 5 == 0) { n/=5; F/=5; }
    while (n % 2 == 0 && F % 2 == 0) { n/=2; F/=2; }
    total += F;
}

out.println(total);

Output:

1
55664090

And then for the purely mathematical solution:

If the tally counter can count N N values, with prime factor decomposition N = p 1 e 1 p 2 e 2 , N = p_1^{e_1} \cdot p_2^{e_2} \cdots, then i = 1 N F ( i ) = k ( p k ( p k 2 e k 1 ) p k + 1 + 1 ) . \sum_{i=1}^N F(i) = \prod_k \left(\frac{p_k(p_k^{2e_k}-1)}{p_k+1}+1\right). (Challenge for all of you: prove this!)

In this case, N = 10000 = 2 4 5 4 N = 10000 = 2^4\cdot 5^4 , and the answer is i = 1 9999 F ( i ) = ( 2 ( 2 2 4 1 ) 2 + 1 + 1 ) ( 5 ( 5 2 4 1 ) 5 + 1 + 1 ) 1 = 171 325521 1 = 55664090. \sum_{i=1}^{9999} F(i) = \left(\frac{2\cdot (2^{2\cdot 4}-1)}{2+1}+1\right) \left(\frac{5\cdot(5^{2\cdot 4}-1)}{5+1}+1\right)-1\\ =171\cdot 325521 - 1 = 55664090.

Arjen Vreugdenhil - 5 years, 6 months ago
Jorge Fernández
Aug 3, 2015

So 090 is wrong? but 90 is correct? how is 90 the last three digits? 90 is two digits. Both should be right, an otherwise 090 should be the only correct answer.

Nilesh Sah
Mar 1, 2014

As simple as:

#include <iostream> 
#include <conio.h>
 using namespace std;

int main() {
  int a=0;
  int mc = 0;
for(int i = 1; i <= 9999; i++) {
        int first = i;
        a = i;
        int count = 1;
        while( a != 0 ) {
               a += i;
               a = a%10000;
               count++;
               count = count%1000;
        }
        mc += count;
        mc %= 1000;
}

  cout << mc;
  getch();
 }
Arthur Komatsu
Feb 15, 2014

Mathematica code: Sum[Length[DeleteDuplicates[Table[FromDigits[Last[Substes[IntegerDigits[10000+n*x],{4}]]],{x,1,10000}]]],{n,1 9999}]

Petko Petkov
Feb 5, 2014

Solution is based on the following observations:

  1. F ( x ) = n g c d ( x , n ) F(x)=\frac{n}{gcd(x,n)}
  2. F ( x ) = F ( n x ) F(x)=F(n-x)

so the following program does the calculation:

#include <iostream>

int gcd(int a, int b){ 
if (b == 0) return a;
else return gcd(b, a % b);
} 

int main(int argc, char** argv) {

int sum=0, i;
for(i=1;i<5000;i++){
    sum += 2 * 10000 / gcd(i, 10000);
}
sum += 10000 / gcd(i, 10000); //for the middle 5000
printf("sum=%d", sum);
return 0;
}

The output is:

sum=55664090

and thus the answer is 090 \boxed{090}

Md. Imrul Hassan
Jan 23, 2014

In Ruby:

(1..9999).inject(0){|s,i|s+=10000/10000.gcd(i)}
Alexander Katz
Jan 7, 2014

First thing we need to notice is that the tally will eventually loop back to 0. Once this happens we know that we have exhausted the distinct possibilities for the tally. Thus we can simply continuously increment some variable by x until we reach 0, and the number of times we increment it is F(x). The rest is simple implementation:

public class Brilliant3{
  public static int tally(int n){
    int ret=1;
    int blah=n;
    while(blah!=0){
      ret++;
      blah+=n;
  blah=blah%10000;}
return ret;}
  public static void main(String[] args){
    int ans=0;
    for(int i=1; i<=9999; i++){
      /*if(i<10){System.out.print(tally(i)+" ");}*/
      ans+=tally(i);}
    System.out.println(ans);
  }
}

nicely named variables

1 2 - 7 years, 4 months ago
Alex Letizia
Jan 3, 2014

int main() {

    int i,remainder,counter,sum;
    i=1;
sum=0;
while(i<10000)
{

    counter=0;
    remainder=1;
    while(remainder!=0)
    {
        remainder=((counter+1)*i)%10000;
        counter++;          
    }       
    sum+=counter;
    i++;
}
printf("The sum is %d\n",sum);
return EXIT_SUCCESS;

}

Clifford Wilmot
Dec 28, 2013

The overflow means we are effectively taking the numbers ( mod 10000 ) (\text{mod}~10000) . Note that if we count up 10000 10000 times, we have effectively added a multiple of 10000 10000 to our counter, hence we only need to consider the results from adding x x the first 9999 9999 times. Now, there are 9999 9999 values of i i and 10000 10000 additions of x x to test for each i i , therefore there are less than one hundred million counter tallies in total, which is easy to brute force using modern computers.

Hence we can use this Python 3.3.0 code (parts of a line after a "#" are comments):

total = 0
for i in range(1, 9999+1):
    shown = set()#  Create a set of counter values for this value of i.
    for k in range(0, 10000):
        shown.add((k*i)%10000)#Use this as an alternative to repeatedly addding i.
    total += len(shown)# len(shown) is F(i)
print(total%1000)# Only want the last three digits.

Running this code gives the answer of 90 90 .

include<stdio.h>

int main() { int nextNumber=0; int addBy; int totalTallyCount=0; int tallyCount=0; int j; int k; int i ; int isFilled[10000];

for(addBy = 1 ; addBy <= 9999 ; addBy++ )
{
    /* Clean the slate */
    for(i=0;i<=9999 ;i++)
    isFilled[i]= 0;

    for (j=0 ;j<=9999 ;j++)
    {
        nextNumber = nextNumber + addBy ;
        while(nextNumber >9999)
        {
            nextNumber = nextNumber -10000 ;
        }
        /* fill the slate */
        isFilled[nextNumber] = 1;
    }

    /* count the number of filled numbers for one addBy */
    for(k=0  ; k<=9999 ;k++)
    {
        if(isFilled[k]== 1 ) tallyCount ++;
    }
    printf("Sum for addBy=%d  = %d \n" ,addBy, tallyCount);
    totalTallyCount = totalTallyCount + tallyCount;
    tallyCount = 0;
}

 printf("Sum = %d" , totalTallyCount);

return 0;

}

Yes the answer is 090!

Antariksh Bhardwaj - 7 years, 4 months ago

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...