银河

SKYIV STUDIO

  博客园 :: 首页 ::  ::  :: 订阅 订阅 :: 管理 ::
  105 随笔 :: 2 文章 :: 751 评论 :: 22 Trackbacks
Timus 1318. Logarithm 要求将一些 128-bit 数进行 XOR 运算后,取对数(只计算到整数部分),然后求它们的和。

1318. Logarithm

Time Limit: 1.0 second
Memory Limit: 16 MB

Given a set A of N unordered 128-bit numbers. You are to compute a value of the function
Problem illustration
where Ak — the kth element of A, log10X — the integer part of the decimal logarithm of X. We’ll assume that log100 = 0.

Input

The first input line contains a number N <= 5000. In the following N lines there are 128-bit numbers Ak presented by sets of numbers (a1k, a2k, a3k, a4k), each of them lies in range from 0 to 232-1. The number Ak can be obtained from this set according to the formula
Ak = 296a1k + 264a2k + 232a3k + a4k.

Output

You are to output the value of the function for the given set.

Sample

inputoutput
2
0 0 0 2324
0 2332 0 0
44
Problem Author: Idea: Nikita Shamgunov, prepared by Nikita Shamgunov, Anton Botov
Problem Source: VIII Collegiate Students Urals Programming Contest. Yekaterinburg, March 11-16, 2004

解答如下:

 1 using System;
 2 using System.IO;
 3 
 4 namespace Skyiv.Ben.Timus
 5 {
 6   // http://acm.timus.ru/problem.aspx?space=1&num=1318
 7   sealed class T1318
 8   {
 9     static void Main()
10     {
11       UInt128[] numbers = UInt128.Read(Console.In);
12       int v = 0;
13       for (int i = 0; i < numbers.Length - 1; i++)
14         for (int j = i + 1; j < numbers.Length; j++)
15           v += UInt128.Log10(UInt128.Xor(numbers[i], numbers[j]));
16       Console.WriteLine(v * 2);
17     }
18   }
19 
20   sealed class UInt128 : IComparable<UInt128>
21   {
22     static readonly int n = 4;
23     static readonly UInt128[] TenPowers;
24     uint[] uint32s;
25 
26     static UInt128()
27     {
28       TenPowers = new UInt128[39]; // Pow(10, 39) > UInt128.MaxValue
29       BigInteger p32 = BigInteger.Pow(232), p64 = p32 * p32, p96 = p64 * p32, k = 1;
30       for (int i = 0; i < TenPowers.Length; i++, k *= 10)
31       {
32         BigInteger r;
33         uint q0 = uint.Parse(BigInteger.DivRem(k, p96, out r).ToString());
34         uint q1 = uint.Parse(BigInteger.DivRem(r, p64, out r).ToString());
35         uint q2 = uint.Parse(BigInteger.DivRem(r, p32, out r).ToString());
36         TenPowers[i] = new UInt128(uint.Parse(r.ToString()), q2, q1, q0);
37       }
38     }
39 
40     UInt128(params uint[] uint32s)
41     {
42       this.uint32s = new uint[n];
43       for (int i = uint32s.Length - 1; i >= 0; i--this.uint32s[i] = uint32s[i];
44     }
45 
46     static UInt128 FromInt32s(string s)
47     {
48       string[] ss = s.Split();
49       return new UInt128(uint.Parse(ss[3]), uint.Parse(ss[2]), uint.Parse(ss[1]), uint.Parse(ss[0]));
50     }
51 
52     public int CompareTo(UInt128 other)
53     {
54       if (other == nullreturn 1;
55       if (uint32s[3> other.uint32s[3]) return 1;
56       if (uint32s[3< other.uint32s[3]) return -1;
57       if (uint32s[2> other.uint32s[2]) return 1;
58       if (uint32s[2< other.uint32s[2]) return -1;
59       if (uint32s[1> other.uint32s[1]) return 1;
60       if (uint32s[1< other.uint32s[1]) return -1;
61       if (uint32s[0> other.uint32s[0]) return 1;
62       if (uint32s[0< other.uint32s[0]) return -1;
63       return 0;
64     }
65 
66     public static UInt128[] Read(TextReader reader)
67     {
68       UInt128[] numbers = new UInt128[int.Parse(reader.ReadLine())];
69       for (int i = numbers.Length - 1; i >= 0; i--) numbers[i] = UInt128.FromInt32s(reader.ReadLine());
70       return numbers;
71     }
72 
73     public static UInt128 Xor(UInt128 x, UInt128 y)
74     {
75       UInt128 v = new UInt128();
76       for (int i = 0; i < n; i++) v.uint32s[i] = x.uint32s[i] ^ y.uint32s[i];
77       return v;
78     }
79 
80     public static int Log10(UInt128 x)
81     {
82       int low = 0;
83       int high = TenPowers.Length - 1;
84       int mid = 0;
85       int cmp = 0;
86       while (low <= high)
87       {
88         mid = (low + high) / 2;
89         cmp = TenPowers[mid].CompareTo(x);
90         if (cmp < 0) low = mid + 1;
91         else if (cmp > 0) high = mid - 1;
92         else return mid;
93       }
94       return mid - ((cmp > 0? 1 : 0);
95     }
96   }
97 }

这个程序的算法是非常直接了当的。程序中用到了 BigInteger 类,其源代码在 浅谈 BigInteger 这篇随笔中。

因为 2128 ≈ 3.4 x 1038,所以在程序中使用一个数组来存储 100, 101, ... 1038 各个数(程序中第 28 行)。在计算对数时,即程序中第 80 行开始的 Log10 方法中,使用二分搜索法在该数组中查找就行了。

这道题目限时是 1.0 秒。问题是我的这个程序运行时会超时,无法 Accept。我想不出来还有什么更快的方法了。谁可以告诉我更好的算法?

posted on 2008-07-14 22:41 银河 阅读(140) 评论(0)  编辑 收藏 所属分类: 算法

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
博客园首页

新闻频道

社区

小组

博问

网摘

闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-07-15 19:15 编辑过
成果网帮您增加网站收入


相关链接: