星辰.Net技术社区论坛

首页 » .NET » 算法/数据结构 » 要求计算出不包括相邻的零的 N 位 K-进制数共有多少个
admin - 2008-7-4 22:04:00
Let’s consider K-based numbers, containing exactly N digits. We define a number to be valid if its K-based notation doesn’t contain two successful zeros. For example: :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
Given two numbers N and K, you are to calculate an amount of valid K based numbers, containing N digits.:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
You may assume that 2 ≤ K ≤ 10; N ≥ 2; N + K ≤ 1800.:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
InputThe numbers N and K in decimal notation separated by the line break.:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
OutputThe result in decimal notation.:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
Sample
inputoutput
2:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
10:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
90:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
答案如下::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
1 using System;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
2 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
3 namespace Skyiv.Ben.Timus:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
4 {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
5  //http://acm.timus.ru/problem.aspx?space=1&num=1013:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
6  sealed class T1013:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
7   {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
8    static void Main():“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
9     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
10      int n = int.Parse(Console.ReadLine()), i = 2;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
11      int k = int.Parse(Console.ReadLine()) - 1;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
12       BigInteger m = 0;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
13      for (BigInteger p = 1, q = k; i <= n; i++, p = q, q = m) m = (p + q) * k;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
14       Console.WriteLine(m);:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
15     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
16   }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
17 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
18  sealed class BigInteger:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
19   {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
20    int[] digits = new int[1800];:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
21 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
22    public BigInteger(int n):“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
23     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
24       digits[0] = n;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
25      if (digits[0] > 9) Format();:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
26     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
27 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
28    public BigInteger(BigInteger x):“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
29     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
30       Array.Copy(x.digits, digits, digits.Length);:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
31     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
32 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
33    public static implicit operator BigInteger(int x):“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
34     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
35      return new BigInteger(x);:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
36     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
37 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
38    public static BigInteger operator +(BigInteger x, BigInteger y):“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
39     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
40       BigInteger z = new BigInteger(x);:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
41      for (int i = x.digits.Length - 1; i >= 0; i--) z.digits= x.digits + y.digits;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
42       z.Format();:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
43      return z;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
44     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
45 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
46    public static BigInteger operator *(BigInteger x, int y):“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
47     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
48       BigInteger z = new BigInteger(x);:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
49      for (int i = x.digits.Length - 1; i >= 0; i--) z.digits = x.digits * y;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
50       z.Format();:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
51      return z;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
52     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
53 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
54    void Format():“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
55     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
56      for (int quotient = 0, i = 0; i < digits.Length; i++):“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
57       {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
58        int numerator = digits + quotient;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
59         quotient = numerator / 10;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
60         digits = numerator % 10;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
61       }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
62     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
63 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
64    public override string ToString():“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
65     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
66      int n = digits.Length - 1;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
67      while (n >= 0 && digits[n] == 0) n--;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
68      if (n < 0) return "0";:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
69      char[] cs = new char[n + 1];:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
70      for (int i = n; i >= 0; i--) cs = (char)(digits[n - i] + '0');:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
71      return new string(cs);:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
72     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
73   }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
74 }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
这道题要求计算出不包括相邻的零的 N 位 K-进制数共有多少个。这里 2 ≤ K ≤ 10; N ≥ 2; N + K ≤ 1800。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
我们还是开始找规律吧。左图是 K = 4,N = 3 的情况。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
我们用 Mn 来表示 n 位 K-进制数的数量。从左图中可以看出::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
M2 = 12, M3 = 45:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
经过仔细观察,我们假设::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
M0 = 1, M1 = 3:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
然后再经过认真分析,我们得到以下规律::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
M0 = 1, M1 = K - 1,  Mn = (K - 1) * (Mn-1 + Mn-2)  (n > 1) :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
在递推公式 Mn = (K - 1) * (Mn-1 + Mn-2) 中::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
系数 K - 1 代表 K-进制数的最高位从 1 到 K - 1:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
Mn-1 代表次高位不为零的情形:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
Mn-2 表示次高位为零的情形:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
然后,对于 K = 2、K = 3 在 N 比较小的情况下验证了这个规律。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
既然有了递推公式,写出相应的程序自然易如反掌。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
但是,要注意,当 K = 10,N = 1790 时,M1790 接近 101790,所以要使用 BigInteger 类来进行计算。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
实际上,这个问题共有三姐妹,分别是::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
1009. K-based numbers时间限制:1.0 秒2 ≤ K ≤ 10; N ≥ 2; N + K ≤ 18
1012. K-based numbers. Version 2时间限制:1.0 秒2 ≤ K ≤ 10; N ≥ 2; N + K ≤ 180
1013. K-based numbers. Version 3时间限制:2.0 秒2 ≤ K ≤ 10; N ≥ 2; N + K ≤ 1800
当然,上面的程序也完全适用于 Timus 1009 和 Timus 1012。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
另外,对于 Timus 1009,把上面程序 Main() 方法中的第 12 和 13 行中的 BigInteger 改为 int 也完全没有问题。因为 int.MaxValue = 2,147,483,647,而我们有::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
NKM
1621,597
153:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
2,781,184
144:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
104,879,772:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
135:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
661,766,144
126:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
1,413,765,625
117:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
1,434,392,064
108:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
837,677,687
9:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
9:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
317,882,368
8:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
10:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
85,096,170
从上表中可以看出,Timus 1009 的输出绝对不会大于 1,434,392,064,所以使用 int 是安全的。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
下面是这个程序的运行情况::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
其中 ID 为 2147015 的记录就是把 BigInteger 改为 int 后的程序的运行结果,运行时间为 0.093 秒。这个结果有点奇怪,因为她比使用 BigInteger 的程序的运行时间 0.078 秒还要大。因为一般来说,用 int 进行运算应该比 BigInteger 快才对。:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
修改后的程序如下所示::“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
1 using System;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
2 :“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
3 namespace Skyiv.Ben.Timus:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
4 {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
5  // http://acm.timus.ru/problem.aspx?space=1&num=1009:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
6  sealed class T1009:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
7   {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
8    static void Main():“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
9     {:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
10      int m = 0, n = int.Parse(Console.ReadLine());:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
11      int k = int.Parse(Console.ReadLine()) - 1;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
12      for (int i = 2, p = 1, q = k; i <= n; i++, p = q, q = m) m = (p + q) * k;:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
13       Console.WriteLine(m);:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
14     }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
15   }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
16 }:“ÁAî%÷î̊www.netcsharp.cn­«”1IècQ¹
1
查看完整版本: 要求计算出不包括相邻的零的 N 位 K-进制数共有多少个