This problem is the more-evil-version of this problem .
A normal long tally counter has 7 digits and counts 1 by 1 , hence there are 1 0 7 different numbers can be shown on it (in range 0 0 0 0 0 0 0 . . . 9 9 9 9 9 9 9 ).
Suppose you have an odd long tally counter. Instead 1 by 1 , it counts x by x . In case of overflow, the counter only shows the last 7 digits of the number.
For example, if x = 1 0 0 0 0 0 1 the counter will show these numbers : 0 0 0 0 0 0 0 , 1 0 0 0 0 0 1 , 2 0 0 0 0 0 2 , . . . , 9 0 0 0 0 0 9 , 0 0 0 0 0 1 0 , 1 0 0 0 0 1 1 , . . .
Let F ( n ) be the function returning the number of different numbers can be shown on odd long tally counter with x = n , find the last 3 digits of ∑ i = 1 1 0 7 − 1 F ( i ) .
As an explicit example : F ( 1 ) = 1 0 7
This problem is taken from TOKI Open Contest January 2013 (Problemsetter : Me)
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.
Careful if you try this in Java! You'll have to use the BigInteger class, since the numbers get quite large.
Nice solution. I did it in the same way.
That exclamation mark may be interpreted as a factorial. It may be nice to \left[ (m,x)=d\right] \frac{m}{\gcd(m,x)} ] = d ∣ m ∑ x = 1 ∑ m [ ( m , x ) = d ] d m = d ∣ m ∑ d m x = 1 ∑ m [ ( m , x ) = d ] [= \sum {d|m} \frac{m}{d} \sum {x=1}^m \left[ (m/d,x/d)=1\right]= \sum_{d|m} \frword it differently to avoid that ambiguity.
First, using the mighty Haskell
let sumOfTally m = sum $ map ((m `div`).(gcd m)) [1..m-1]
Then sumOfTally (10^7) is our answer. Instead of 10^7 I will consider the general case of m. We can compute F ( x ) = g c d ( m , x ) m , and we know that because when adding to the tally, we are always in k x m o d m for some k . Then d = g c d ( m , x ) will always divide k x and m so that reminder will be divisible by d. Furthermore, appart from g c d ( x / d , m / d ) = 1 , so factoring the d, it will give relative prime numbers, so it will pass through every number modulo m / d . And that is fast enough O ( n lo g n ) (Great Common Denominator is really O(log n) where n is the smaller number). Some five, ten seconds maybe.
But we can do better. I will use the notation that [P] is 1 when P is true, 0 when is false. And that $gcd(x,y)$ divides both x and y. To simplify things, I will sum until i=m, then substract that case (Note that F(m)=1)
i = 1 ∑ m F ( i ) = x = 1 ∑ m g cd ( m , x ) m = d ∣ m ∑ x = 1 ∑ m a c m d y = 1 ∑ m / d [ ( m / d , y ) = 1 ] = d ∣ m ∑ d m ϕ ( d m ) = d ∣ m ∑ d ϕ ( d )
Coding phi is standard, as well as getting the list of divisors, and you can make some optimizations by knowing already the factorization of m But we can still do better, at least we can have a nicer code. Bottomline, the bottleneck would be factorizing m still.
By the theory of multiplicative functions, if that thing I name it G ( m ) , then G(m) is multiplicative, because 1 / n is multiplicative, as well as p h i and G is the convolution of both things. That means that if m = ∏ i = 1 r p i a i then G ( m ) = ∏ i = 1 r G ( p i a i ) . So lets calculate G ( p k ) .
G ( p k ) = 1 + ( p 2 − p ) + ( p 4 − p 3 ) + . . . + ( p 2 k − p 2 k − 1 = t = 0 ∑ 2 k ( − p ) t = p + 1 p 2 k + 1 + 1
So with all this have now a nice formula for the sum (plus 1). To wrap this, lets do some code in Haskell.
import Data.List
primes = 2:filter (\k-> and [rem k p>0|p<-takeWhile ((<=k).(^2)) primes]) [3,5..]
numFactors p n = genericLength $ takeWhile ((==0).(flip rem p)) $ iterate (`div` p) n
factorFrom p n = head $ dropWhile ((==0).(flip rem p)) $ iterate (`div` p) n
factors (p:ps) n
| n==1 = 1
| rem n p == 0 = (p,numFactors p n):factors ps (factorFrom p n)
| otherwise = factors ps n
sumOfTally n = (-1) $ product $ map (\(p,k)->(p^(2*k+1)+1) `div` p+1) $ factors primes n
Little bit faster.
It trails off the solution, so I will write G again here. G ( p k ) = p + 1 p 2 ∗ k + 1 + 1
Two bugs in the last code, it is actually
import Data.List
primes = 2:filter (\k-> and [rem k p>0|p<-takeWhile ((<=k).(^2)) primes]) [3,5..]
numFactors p n = genericLength $ takeWhile ((==0).(flip rem p)) $ iterate (`div` p) n
factorFrom p n = head $ dropWhile ((==0).(flip rem p)) $ iterate (`div` p) n
factors (p:ps) n
| n==1 = []
| rem n p == 0 = (p,numFactors p n):factors ps (factorFrom p n)
| otherwise = factors ps n
sumOfTally n = pred $ product $ map (\(p,k)->(p^(2*k+1)+1) `div` (p+1)) $ factors primes n
Python Sol::::
def F1(k, num):
tally, i = [], 0
if i % 2 == 1 and i % 5 != 0:
return num
m, n = fac2(k), fac5(k)
return make(m, n, num)
def make(m, n, num):
for i in range(m + 1)[::-1]:
for j in range(n + 1)[::-1]:
res = num/float((2**i)*(5**j))
if res == int(res):
return int(res)
def F(k, num):
tally, i = [], 0
while True:
if len(tally) < 2:
tally.append((k*i)%num)
elif tally[-1] == tally[0]:
tally.pop()
return len(tally)
else:
tally.append((k*i)%num)
i += 1
def fac2(n):
times = 0
while n > 0:
if n%2 == 0:
times += 1
else:
return times
n = n/2
def fac5(n):
times = 0
while n > 0:
if n%5 == 0:
times += 1
else:
return times
n = n/5
tot = 0
for i in range(1, 10000000):
tot += F1(i, 10000000)
Hard Realization of this simple code:
def F(k, num):
return num/gcd(k, num)
def gcd(a, b):
m = max(a, b)
n = min(a, b)
if m % n == 0:
return n
if m % n == 1:
return 1
else:
return gcd(m % n, n)
tot = 0
for i in range(1, 10**7):
tot += F(k, num)
print tot
Log in to reply
The main key is to proof that F ( n ) = G C D ( n , 1 0 7 ) 1 0 7
Once you get it, just use a single loop + Euclid's algorithm to get the answer.
The proof of F ( n ) is left as an exercise, :)
Interestingly, this problem (at the moment of writing this comment) has a lower rating than its "not-evil" counterpart (2249 vs 2257).
:3
1 2 3 4 5 6 7 8 9 10 11 |
|
It's the same program (solution) as for the other problem but this time we have to take care not to overflow the int type so we just need to keep the sum modulo 1000:
#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<5000000;i++){
sum += 2 * 10000000 / gcd(i, 10000000);
sum %= 1000;
}
sum += 10000000 / gcd(i, 10000000); //for the middle 5000000
sum %= 1000;
printf("sum=%d", sum);
return 0;
}
The output is:
sum=382
=MOD(14 (4^k-1)+500 (k-1)+20,1000) for tally counter with k digits
=382 for k=7
basically ignore most results (or combinations of results) that add multiples of 1000 to the sum, so consider only few cases F(5^k 2^m),F(5^(k-1) 2^m),F(2^7*5^m) for some m
In Ruby:
(1..9999999).inject(0){|s,i|s+=10000000/10000000.gcd(i)}
Mathematically: F(x) = N/GCD(x,10^7). Used Excel to Compute SUM(F(x)) for x=1 to 9,999,999 . ( Use Datable after calculating from 0 to 999,999). For Excel file you can send a request at www.excelmagicpro.com by going in the interest form section under Contact.
We need to find the least multiple which devides 10^7 and n and then devide it by n. It is easier if we just remove the common devisors of both from 10^7. 10^7 is only devided by 2^7 and 5^7 which makes our work easier: import sys
def counter(number,upper):
i=1
while i<8:
if number%(2**i)==0:
i=i+1
else:
break
upper=upper/2**(i-1)
i=1
while i<8:
if number%(5**i)==0:
i=i+1
else:
break
upper=upper/5**(i-1)
return upper%1000
sum=0
for i in range(1,10000000):
if i%10000==0:
print i
sum=sum+counter(i,10000000)
if sum>=1000:
sum=sum%1000
print sum
Basically, F ( n ) = g c d ( 1 0 7 , n ) 1 0 7 . Using just that fact alone, I was able to get a runtime of about 3 seconds. However, one can also note that F ( n ) = F ( 1 0 7 − n ) .Therefore, we find the sum from 1 to 10^7/2 - 1, double that, and add 2 (to account for F(10^7/2) = 2), which cuts runtime in half to 1.5 s.
I feel like there's an even more clever way involving the totient function and the divisors of 10^7, but I can't come up with one atm.
Problem Loading...
Note Loading...
Set Loading...
If we examine the problem, we see that for a given number n from 1 to 1 0 7 , F ( n ) is equal to g c d ( 1 0 7 , n ) 1 0 7 because the counter repeats at every multiple of g c d ( 1 0 7 , n ) . For example, if n = 1 0 0 , then g c d ( 1 0 7 , n ) is 1 0 0 , therefore 1 0 0 divides into 1 0 7 100 times, and finally F ( 1 0 0 ) is 1 0 5 . We then just add the values of F ( n ) from 1 to 1 0 7 , like this in Python:
This executes in less than 5 minutes on my laptop.