最近,我的计算机代数系统课程正在进行中。我从Project Euler中随机分配了一个问题来解决(问题520)。问题如下:
"我们将 simber 定义为正整数,其中任何奇数位, 如果存在,则发生奇数次,以及任何偶数,如果 现在,发生了偶数次。
例如,141221242是一个9位数的simber,因为它有三个1, 4个2&2和4个。
设Q( n )为最多 n 位的所有simbers的数量。
给予Q(7)= 287975和Q(100)mod 1 000 000 123 = 123864868。
查找(Σ1≤u≤39Q(2 ^ u))mod 1 000 000 123。"
该课程要求我使用Wolfram-Mathematica使用高效编码来解决问题。下面的代码是我的Q函数( n )。我已经收录了评论,以帮助浏览我的编码。
Q[x_] := (
s = 0; (*Initalizes simber count*)
For[i = 1, StringLength[ToString[i]] <= x,
i++,(*Starts at 1 and continues until number is no longer 'x' digits long*)
num = ToString[i]; (*Sets 'num' to 'i' in string form*)
While[num != "", (*Loops until 'num' string is blank*)
If[EvenQ[
ToExpression[
Characters[num][[
1]]]], (*If the first digit of 'num' is Even*)
If[EvenQ[
StringCount[num,
Characters[num][[
1]]]], (*Checks if there are an Even quantity of the first digit in the string*)
num =
StringDelete[num,
Characters[num][[
1]]]; (*Removes all digits in the string that is the first digit e.g. 43442421 => 3221*)
If[num == "", (*If string is blank, increase simber count*)
s++;
]
,(*else*)
num =
"" (*If first digit is Even but not and Even quanity sets num to "" to break loop *)
]
,(*If the first digit of 'num' is Odd*)
If[OddQ[
StringCount[num,
Characters[num][[
1]]]], (*Checks if there are an Odd quantity of the first digit in the string*)
num = StringDelete[num, Characters[num][[1]]];
(*Removes all digits in the string that is the first digit e.g.
3292133 => 2921*)
If[num == "",(*If string is blank, increase simber count*)
s++;
]
,(*else*)
num =
"" (*If first digit is Odd but not and Odd quanity sets num to "" to break loop *)
]
]
]
];
s (*Displays final simber count*)
)
我用Q [7]对此代码进行了测试,以验证结果为287975.但是,处理Q [7]的时间需要6分钟。随着 n 的值增加,处理代码的时间会呈指数级增长。
任何帮助或建议缩短处理时间,还是我从错误的角度接近欧拉问题?
答案 0 :(得分:2)
首先,你的代码非常好,臃肿。这可以更容易写下来
isSimber[int_Integer] := isSimber[IntegerDigits[int]];
isSimber[digits_List] := And @@ Equal @@@ EvenQ[Tally[digits]]
q[n_] := Count[isSimber /@ Range[0, 10^n - 1], True]
q[7] // Timing
(* {58.328, 287975} *)
第二,是的,我相信你需要进一步思考这个问题。只需看看你,你的方法,需要迭代到2 ^ 39位数字。看看一个简单的Do
循环u
仅 3已经21秒。绝对没有发生任何事情,更不用说计算了:
Do[
x = i,
{i, 10^(2^3)}
] // Timing
我们甚至没有开始考虑记忆。所以,是的,你目前的方法是行不通的。