Advertisement
Guest User

Auction

a guest
Jan 27th, 2012
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.02 KB | None | 0 0
  1. #!/usr/bin/env python
  2. import os, sys
  3.  
  4. def time_function(func):    
  5.     def wrapped_func(*args, **kwargs):
  6.         from time import time
  7.         start = time()
  8.         res = func(*args, **kwargs)
  9.         sys.stderr.write('%s took %.6fs\n' % (func.__name__, time() - start))
  10.         return res
  11.     return wrapped_func
  12.  
  13. class Auction(object):
  14.     @time_function
  15.     def __init__(self, n, p1, w1, m, k, a, b, c, d):
  16.         self.n = n        
  17.         self.p_head, self.p_tail, self.p_lookup = self.gen_func(a, b, p1, m)
  18.         self.w_head, self.w_tail, self.w_lookup = self.gen_func(c, d, w1, k)
  19.         self.p_total = self.p_head + self.p_tail
  20.         self.w_total = self.w_head + self.w_tail
  21.         self._p_head = len(self.p_head)
  22.         self._p_tail = len(self.p_tail)
  23.         self._w_head = len(self.w_head)
  24.         self._w_tail = len(self.w_tail)
  25.         self._gcd = self.gcd(self._p_tail, self._w_tail)
  26.         self._period = (self._p_tail * self._w_tail)/self._gcd
  27.         self.w_total.sort()
  28.         self.p_total.sort()      
  29.         self.w_s_lookup = dict((v, i) for i, v in enumerate(self.w_total))
  30.         self.p_s_lookup = dict((v, i) for i, v in enumerate(self.p_total))
  31.  
  32.     def gen_func(self, a, b, p0, m):
  33.         p = [p0]
  34.         __p  = { p0 : 0 }
  35.         p_pattern = 0
  36.         i = 1
  37.         b = b % m
  38.         a = a % m
  39.         while i < self.n:
  40.             p_n = ((a * p[i-1] + b) % m) + 1
  41.             if p_n in __p:
  42.                 p_pattern = __p[p_n]
  43.                 break
  44.             p.append(p_n)
  45.             __p[p_n] = i
  46.             i += 1
  47.         return p[:p_pattern], p[p_pattern:], __p
  48.    
  49.    
  50.     def gcd(self, a, b):
  51.         b, a = min(a, b), max(a, b)
  52.         if b == 0:
  53.             return a
  54.         return self.gcd(b, a % b)
  55.    
  56.     @time_function
  57.     def get_deals(self):
  58.         min_p, max_p = 0, len(self.p_total) - 1
  59.         min_w, max_w = 0, len(self.w_total) - 1
  60.         bargains = 0
  61.        
  62.         while max_p >= min_p and max_w >= min_w:        
  63.             if max_p - min_p <= max_w - min_w:
  64.                 p = self.p_total[min_p]
  65.                 w, c = self.get_w(p, min)
  66.                 if self.w_s_lookup[w] <= max_w:
  67.                     bargains += c
  68.                     w_pos = self.w_s_lookup[w]
  69.                     if w_pos == 0:
  70.                         break
  71.                     max_w = w_pos - 1
  72.                 min_p += 1            
  73.             else:
  74.                 w = self.w_total[min_w]
  75.                 p, c = self.get_p(w, min)
  76.                 if self.p_s_lookup[p] <= max_p:
  77.                     bargains += c
  78.                     p_pos = self.p_s_lookup[p]
  79.                     if p_pos == 0:
  80.                         break
  81.                     max_p = p_pos - 1
  82.                 min_w += 1
  83.                
  84.         min_p, max_p = 0, len(self.p_total) - 1
  85.         min_w, max_w = 0, len(self.w_total) - 1
  86.         terrible = 0
  87.        
  88.         while max_p >= min_p and max_w >= min_w:            
  89.             if max_p - min_p <= max_w - min_w:
  90.                 p = self.p_total[max_p]
  91.                 w, c = self.get_w(p, max)
  92.                 if self.w_s_lookup[w] >= min_w:
  93.                     terrible += c
  94.                     w_pos = self.w_s_lookup[w]
  95.                     min_w = w_pos + 1
  96.                 max_p -= 1            
  97.             else:
  98.                 w = self.w_total[max_w]
  99.                 p, c = self.get_p(w, max)
  100.                 if self.p_s_lookup[p] >= min_p:
  101.                     terrible += c
  102.                     p_pos = self.p_s_lookup[p]
  103.                     min_p = p_pos + 1
  104.                 max_w -= 1      
  105.         return terrible,bargains
  106.        
  107.     def get_w(self, p, func):
  108.         pos_p = self.p_lookup[p]
  109.        
  110.         if pos_p < self._p_head:
  111.             return self.get_w_for_pos(pos_p), 1
  112.         i = 0
  113.         ws = []
  114.         lp = (self._w_head + self._period)/self._p_tail
  115.         while i < lp:
  116.             if pos_p + i * self._p_tail >= self.n:
  117.                 break
  118.             ws.append((self.get_w_for_pos(pos_p + i * self._p_tail), pos_p + i * self._p_tail))
  119.             i += 1
  120.         w, pos = func(ws)
  121.         if pos < self._w_head:
  122.             return w, 1
  123.    
  124.         c = (self.n - pos)/self._period
  125.         if (self.n - pos) % self._period > 0:
  126.             c += 1
  127.         return w, c
  128.            
  129.     def get_w_for_pos(self, pos):
  130.         if pos < self._w_head:
  131.             return self.w_head[pos]
  132.         return self.w_tail[(pos - self._w_head) % self._w_tail]
  133.  
  134.     def get_p(self, w, func):
  135.         pos_w = self.w_lookup[w]
  136.        
  137.         if pos_w < self._w_head:
  138.             return self.get_p_for_pos(pos_w), 1
  139.         i = 0
  140.         ps = []
  141.         lp = (self._p_head + self._period)/self._w_tail
  142.         while i < lp:
  143.             if pos_w + i * self._w_tail >= self.n:
  144.                 break
  145.             ps.append((self.get_p_for_pos(pos_w + i * self._w_tail), pos_w + i * self._w_tail))
  146.             i += 1
  147.         p, pos = func(ps)
  148.         if pos < self._p_head:
  149.             return p, 1
  150.    
  151.         c = (self.n - pos)/self._period
  152.         if (self.n - pos) % self._period > 0:
  153.             c += 1
  154.         return p, c
  155.            
  156.     def get_p_for_pos(self, pos):
  157.         if pos < self._p_head:
  158.             return self.p_head[pos]
  159.         return self.p_tail[(pos - self._p_head) % self._p_tail]
  160.  
  161. def get_solution(q, i, args):
  162.     result = Auction(*args).get_deals()
  163.     q.put((i, result))
  164.    
  165. @time_function
  166. def main(args):
  167.     input_file = open(os.path.join(os.path.dirname(__file__), args[0]))
  168.     n = int(input_file.readline().strip())
  169.     output_file = open(os.path.join(os.path.dirname(__file__), 'output.txt'), 'w')
  170.     for i in range(1, n + 1):
  171.         data = map(int, input_file.readline().strip().split(' '))
  172.         b, t = Auction(*data).get_deals()
  173.         output_file.write('Case #%d: %d %d\n' % (i,b,t))
  174.     output_file.close()
  175.     input_file.close()
  176.  
  177. if __name__ == '__main__':
  178.     from doctest import testmod
  179.     print testmod()
  180.     main(sys.argv[1:])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement