一道小学题目
偶尔看到的,题目大致如下:
有一个数,abcdefghi,每个字母分别代表了1到9之间的数字(数字不重复),而且该数有一个特性,a能被1整除,ab能被2整除,...abcdefghi能被9整除,求该数。
反正我是不知道小学方法该怎么求,看到这题目,第一反应就是,循环一下就好了——确实最简单的方法,不过要写的循环太多,也容易出错。
再一分析,这不是个递归的过程么,即该数能被本身长度所整除。试了一下,果然出结果了。
代码如下,为了写起来方便,加了两个扩展方法。
namespace ConsoleApplication1
{
static class Program
{
static int total = 0;//看看递归了多少次
const int LENGTH_OF_NUMBER = 9;
static void Main(string[] args)
{
string[] list = new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
Console.WriteLine("结果是:{0},共运算:{1}次",GetNumber("",list),total);
Console.ReadKey();
}
/// <summary>
/// 递归取得正确的数
/// </summary>
/// <param name="str">当前的字符串</param>
/// <param name="list">剩余可用的字符列表</param>
/// <returns>错误返回空字符串,无错但是可以继续,则返回下一个字符,成功则返回结果</returns>
static string GetNumber(string str, IEnumerable<string> list)
{
total++;
if (str.Length > 0)
{
//如果当前条件都不满足,后续的就没必要继续了
if (!str.CanDivBy(str.Length))
return "";
else if (str.Length == LENGTH_OF_NUMBER) //得到符合的数了,也就没必要继续了
return str;
}
foreach (var v in list)
{
string tmp = GetNumber(str + v, list.NewList(v));
if (tmp.Length != LENGTH_OF_NUMBER)
continue;
else
{
return tmp;
}
}
return "";
}
/// <summary>
/// 是否能被某个整数整除
/// </summary>
/// <param name="val_str"></param>
/// <param name="div"></param>
/// <returns>是否可以被整除</returns>
public static bool CanDivBy(this string val_str, int div)
{
long val;
if (!long.TryParse(val_str, out val))
return false;
return (val * 1.0 / div - val / div) == 0;
}
/// <summary>
/// 根据当前列表,生成一个不包含指定数的新列表
/// </summary>
/// <param name="old_list"></param>
/// <param name="val"></param>
/// <returns></returns>
public static IEnumerable<string> NewList(this IEnumerable<string> old_list, string val)
{
int v = int.Parse(val);
return from a in old_list where int.Parse(a) != v select a;
}
}
}
结果是:381654729,共运算:523次
比我想像的次数少一些。
请无视代码中混乱的命名,纯粹一时兴起验证一下。
题目还可以改一下,即可以加上0,变成abcdefghij可以被10整除,只要把长度改成10,数组里加个0就好了

浙公网安备 33010602011771号