You are on page 1of 3

At first note that for x = 1 the answer is obviously zero because n x in this case has no divisors greater than

n n . So assume that x 2 . Now n x has at least one divisor greater than n (one of such divisors is n x ). Denote by d min (n, x ) the minimal divisor of n x that is greater than n . We need to find the number of those n for which d min (n, x ) b . Denote this number by N ( x, b ) . Not that each divisor of n x that is greater than n has the form n x / k for some k { , 2, ..., x 1} . 1 1 Lets fix some k { , 2, ..., x 1} and count the number of those n for which d min (n, x ) = n x / k and d min (n, x ) b . Denote this number by N k ( x, b ) . It is easy to see that N ( x, b ) = N1 ( x, b ) + N 2 ( x, b ) + ... + N x 1 ( x, b ) . (1)
Note that d min (n, x ) = n x / k if and only if k divides n x but for k < j < x number j does not divide j n x . It is easy to show that j divides n x if and only if j x := divides n . Since k divides n x then gcd ( x, j ) k x divides n and hence n = k x m for some m . Let k < j < x . Number j does not divide n x = k x x m if So if we find an efficient way how to find N k ( x, b ) for 1 k < x the whole problem will be solved.

and only if v j := j / gcd ( j , k x x ) does not divide m . Further note that

bk b m c := . kx x x / gcd ( x, k ) Thus N k ( x, b ) is equal to the number of positive integers m c such that v j does not divide m for
d min (n x ) b n x b k m
k < j < x . Before we find this number try to delete some unnecessary values v j . Obviously we can delete repe-

titions among v j . But it is not enough for efficient calculation. Note that if v j divides vi then we can delete vi because if v j does not divide m then vi also does not divide m . Lets do all such possible deletions. Now denote by a1 , a2 ,..., a p all remaining values v j . Finding of N k ( x, b ) can be done by inclusion-exclusion principle. Denote by A j the set of all positive in-

tegers that is divisible by a j and not greater than c . It is easy to see that N k ( x, b ) = c A1 ... Ap . By inclu-

sion-exclusion principle A1 ... Ap =

1 j1 <...< j r p 1 r p

( 1)

r 1

A j1 ... A jr . Note that A j1 ... A jr is the set of all

positive integers h c that is divisible by a j1 , ..., a jr or equivalently by lcm a j1 ,..., a jr . Hence

c A j1 ... A jr = . lcm a j1 ,..., a jr Using this formula and the fact that the least common multiply of the empty set is equal to one we obtain c r N k ( x, b ) = ( 1) (2) . 1 j1 <...< jr p lcm a j1 ,..., a jr

Using well-known technique we can calculate N k ( x, b ) by the recursive procedure. But it performs very slow for x = 58 and x = 59 for some values of k . So we need to find more efficient way. The main idea is to consider together all terms of sum in (2) that has equal lcms in the denominator and of course only those terms for which such lcm is not greater than c . For each such lcm L we need to know the r sum of all ( 1) that correspond to it. Denote this sum by coef (L ) . Then (2) takes the following form c (3) N k ( x, b ) = coef (L ) . L L In order to explain how to find efficiently the set of all different lcms with their coefficients we need to introduce some formal definitions and notations. For D denote by lcm(D ) the least common multiply of all numbers in D . For A let B be the set of different lcms of subsets of A that is not greater than c , that is B = {lcm(D ) : D A} { , 2, ..., c}. 1 Denote by S A the set of all pairs (L, coef (L )) where L runs through B and coef (L ) is defined as above,
that is coef (L ) is equal to the sum of ( 1)
D

0 r p

where D runs through all subsets of A with lcm equal to L :

S A = {(L, coef (L )) : L B},

coef (L ) =

Hence in order to obtain S i we need to append to the array that contains S i1 all pairs (lcm(L, ai ), f ) where

to see that it gives no more than two pairs for S i : (L, f ) and (lcm(L, ai ), f ) if lcm(L, ai ) c (when we add ai ~ ~ ~ D D to some D for which lcm(D ) = L we obtain D = D {ai } with lcm D = lcm(L, ai ) and ( 1) = ( 1) ).

culate N k ( x, b ) using (3). Now we show how S i can be calculated from S i1 . Let (L, f ) Si 1 . Then it is easy

For 0 i p let Ai = {a1 ,..., ai } and S i = S Ai . Note that S 0 = {(1,1)}. We need to find S p . Then we can cal-

D A lcm ( D )= L

( 1)

( )

if for given L new array contains pairs (L, f1 ),...(L, f q ) then we need to replace these pairs by the pair

(L, f ) S i1 and

lcm(L, ai ) c , sort this new array and then merge in one pair all pairs with common L , that is

Let for the given x we need to find N ( x, b ) for several values of b . Then for each k { , 2, ..., x 1} we will 1 have several values of c corresponding to these values of b . Lets do the following. Calculate S p for the

Thus we obtain the method how to calculate N k ( x, b ) efficiently. Now we can solve the problem using formula (1) for N ( x, b ) . But if you accurately implement the described solution you will get verdict Time Limit Exceeded. There is a series of improvements that needs to be done. 1. Note that finding S p consumes considerably more time than calculating N k ( x, b ) by the formula (3).

(L, f

+ ... + f q ) .

maximal value of c . And then calculate N k ( x, b ) for all values of b by the formula (3) using this one set S p .

Obviously it contains all sets S p for other values of c . So calculation will be correct. I guess that this improvement is critical and without it there is no chance to pass the time limit. However contestants proved a contrary. This improvement can be done as follows. Read all input pairs ( x, b ) . Sort them by x . For the given x find N ( x, b ) for all b that present for this x by the method mentioned above (and with optimizations mentioned below). Finally print the answers in the required order. The next three optimizations are quite easy to implement but together they give improvement about in three times. 2. Note that for each k at first you obtain the collection Tk = ((a1 ,..., aq ), c ) and then calculate N k ( x, b ) by the formulas (2) and (3). Interestingly that for some x for different values of k we can obtain equal collections Tk . Hence we can save this collection for each k with calculated value of N k ( x, b ) and when for some k we obtain collection Tk that was before we simply take the saved answer for this collection. If you use first improvement then you need to save for each k the collection of values N k ( x, b ) for all b that present for this x .

3. Note that if coef (L ) = 0 then we can safely skip this value of L in the sum in (3). Hence we can save in S i only those pairs (L, coef (L )) for which coef (L ) 0 . So when after sorting you merge pairs (L, f1 ),...(L, f q )

you can skip this value of L if f1 + ... + f q = 0 .

4. When you create S i , for each pair (L, f ) you append the new pair (lcm(L, ai ), f ) . Note that ai ai lcm(L, ai ) = L = L . gcd (ai , L ) gcd (ai , L mod ai ) Hence before you start the process of appending pairs to S i1 you can store in some array values ai / gcd (ai , k ) for 0 k < ai say mult[k ] = ai / gcd (ai , k ) . Then at each appending you can calculate lcm(L, ai ) by the formula lcm(L, ai ) = L mult[L mod ai ] . With optimizations 1-4 you can obtain a program that uses about 70-75% of time on the worst test case. But you need to write it optimized enough. There is also one more optimization that decreases this percent to 38-42%. But it is somewhat hard to implement. In a few words it optimizes the process of sorting the set of pairs from S i1 after we append to it new pairs constructed by ai . Lets explain it in details.

Note that mult[k ] is some divisor of ai . Since ai < x 60 then it has no more than 10 divisors. Namely
the only number that has 10 divisors is 48 and all other numbers less than 60 have less than 10 divisors. Let ai corresponds to the divisor d j . Initially all A[ j ] are empty. We iterate through pairs (L, f ) from S i1 in increashas t divisors 1 = d 0 < d1 < ... < d t 1 = ai . Create a special array for each divisor of ai . Let A[ j ] be an array that ing order of L . At each step we consider some pair (L, f ) . Let mult[L mod ai ] = d j . Then we append pair

L . Now we need to merge this t arrays and S i1 as mentioned before. But instead of just appending all this arrays in one, sorting it and then performing merging of pairs we do the following. At each step we will take two arrays with the least sizes, merge them in linear time in new array and replace these two arrays by this new one. This method appears to be almost two times faster than the previous one. Note that if all arrays have equal size then this process is equivalent to the merge sort. However there is another little trick that can be made for this new method. Note that A[0] contains some pairs (L, f ) where (L, f ) is the pair from S i1 . But when we merge pairs (L, f ) and (L, f ) we obtain pair

(L, f ) in strictly increasing order of

(L d , f ) to
j

A[ j ] if L d j c . In the end we obtain t arrays A[0], A[1],..., A[t 1] where each array has pairs

with zero coefficient. Hence we will change the role of A[0] . Let it contains merged arrays S i1 and A[0] in the previous sense. In practice it means that when mult[L mod ai ] = 1 then we dont do any appending, but when we add pair (L, f ) to A[0] . Now in the end we need merge only arrays A[0], A[1],..., A[t 1] without S i1 . find j by mult[L mod ai ] in constant time. P. S. I cant prove analytically why for x = 58 and x = 59 the recursive procedure performs very slow but this method with sorting of pairs performs fast enough for all x and k . The specific of this problem is that you can take maximal possible value of b , run your program for all values of x (there are only 60 such values) and you will see for which values of x its fast enough and for which not. I obtained this solution exactly using this way. I started with recursive procedure and saw that it performs very well for almost all values of x . But for big enough primes and double primes it was very slow. Then I figured out this method with sorting of pairs and unexpectedly it performs very well for all values of x 60 . After that during some period of time I found all these improvements. mult[L mod ai ] = d j > 1 then we do usual appending of the pair (L d j , f ) to A[ j ] if L d j c and additionally Besides since ai < 60 then we can create an array ind[] of size ai such that ind[d j ] = j . This allows us to

You might also like