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:
- 1010230 is a valid 7-digit number;
- 1000198 is not a valid number;
- 0001235 is not a 7-digit number, it is a 4-digit number.
:Á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
| input | output |
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¹当然,上面的程序也完全适用于 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¹| N | K | M |
| 16 | 2 | 1,597 |
| 15 | 3:ÁAî%÷îÌwww.netcsharp.cn«1IècQ¹
| 2,781,184 |
| 14 | 4:ÁAî%÷îÌwww.netcsharp.cn«1IècQ¹
| 104,879,772:ÁAî%÷îÌwww.netcsharp.cn«1IècQ¹
|
| 13 | 5:ÁAî%÷îÌwww.netcsharp.cn«1IècQ¹
| 661,766,144 |
| 12 | 6:ÁAî%÷îÌwww.netcsharp.cn«1IècQ¹
| 1,413,765,625 |
| 11 | 7:ÁAî%÷îÌwww.netcsharp.cn«1IècQ¹
| 1,434,392,064 |
| 10 | 8:Á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¹