特拉亨伯格(Trachtenberg)速算(转载)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了特拉亨伯格(Trachtenberg)速算(转载)相关的知识,希望对你有一定的参考价值。
参考技术A原文链接: https://www.jianshu.com/p/cfda37aaedb1
前两天看电影《天才少女》(2017年),在影片中,主角麦肯娜·格瑞丝小女孩(Mckenna Grace) 学会了一种叫做特拉亨伯格(Trachtenberg)的速算系统,感觉很有意思。于是我在网上搜索,在这儿给大家做一个简介,希望也能激起你们的兴趣,并掌握这种速算方法。由于名字太长不好记,我把它简称为:“特速算”。
特速算的作者,是俄国的数学家 Jakow Trachtenberg (1888-1953),据说是在二战期间,被关进[纳✲粹]集中营,在狱中,他开发出这套心算算法。这套算法后来被命名为Trachtenberg(特拉亨伯格)速算系统。
如果想系统的学习,还可以深入看一下英文版图书《The Trachtenberg Speed System of Basic Mathematics》, 由 Ann Cutler和Rudolph McShane 编译。
这儿,我先做个基本的入门介绍,整理给大家。大致按以下内容来讲:
传统的方法,大家都非常熟悉,我们就以电影中 麦肯娜·格瑞丝 做的这道题为例。
如果把这个步骤拆解细一点的话,应该是这样的:
很显然,作为普通的我们来说,要想在大脑中按照这种思路进行心算,最难的应该有两点:
因为太多了,所以很容易搞混淆。为了解决这样的困扰,特拉亨伯格想出的这套特速算,比较好的解决了这种一次运算过多以及位置对齐的问题。
他将中间计算过程进行 分步骤 ,每一步都只做 个位数的乘法和加法 ,所以,很容易在大脑暂时记忆这些中间计算结果。
下面先以乘数是两位数的上述例子,采用特速算的方式重新来看一下其计算步骤。
大脑具体运算过程和记忆方法如下图示意(每个人有自己的记忆方法,这儿做个示意,供你参考):
下面从末尾倒向开始进行特速算,注意只关注当前计算的位。
我们用实心圆点表示对所指示的计算,提取乘法结果的个位(如下图中的值:5)。
我们用空心圆点表示对所指示的计算,提取乘法结果的十位。也即是上一次计算的十位(如上一图的值:3)。
最终,将暂存在大脑中的数相加,放入最终结果的首位(可能是 0🔔,就不必放了)。
再采用联想记忆,给最终结果编排一个故事:
在你的大脑中想象那画面吧😋。
下面再以乘数是三位数的上述例子,采用特速算的方式继续看一下其计算步骤。
下面从末尾倒向开始进行特速算,注意只关注当前计算的位。
采用上述办法,依次类推下面的 5、6步。
接下来我们看稍微有点差异的7、8步。
最终,将暂存在大脑中的数相加,放入最终结果的首位(可能是 0🔔,就不必放了)。
再采用联想记忆,给最终结果编排一个更生动的故事:
当然,你也可以按2位数字谐音,重新编个故事(怎么有意思就怎么编):
再一次,在你的大脑中想象那画面吧😋,这样,你就记住了最终结果。
通过以上步骤,掌握了特速算的方法后,再来看常用到的两位数乘法,就显得容易多了。比如, 你去买猪肉,¥23/斤,重约 3.8 斤,得花多少钱呢?很显然快速分3步:
一看,我的个乖乖,快 ¥100大洋了,少买点吧,吃不起了,吃不起了…… 🙉🙈🙊🐵
当然,这种过于简单的也不一定非得要用特速算,比如上例中,如果我把重量毛算成 4斤,再减2两,就是 23 × 4 ﹣ 23 × 0.2 = 92 - 4.6 = ¥87.4,也能很快的算出来。但如果是3位数的运算,这种简单的心算又不适合了。所以,我们还是要根据情况灵活使用各种速算方法。
好的,基本的特速算方法就是这样咯,不管怎样得多练习一下才能流利的使用。另外,在《The Trachtenberg Speed System of Basic Mathematics》一书中,还提供了各种特殊乘数(比如: ×11等)的运算方法,可以去深入的发掘。后面空了我再来补充介绍一下。
在 C++ 中加速算法
【中文标题】在 C++ 中加速算法【英文标题】:Speeding up algorithm in C++ 【发布时间】:2016-05-13 17:46:39 【问题描述】:TL;DR:我的代码在 Java 中“很快”,但在 C++ 中却慢得要命。为什么?
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int read(string data, int depth, int pos, vector<long>& wantedList)
// 91 = [
if (data.at(pos) == 91)
pos++;
// Get first part
pos = read(data, depth + 1, pos, wantedList);
// Get second part
pos = read(data, depth + 1, pos, wantedList);
else
// Get the weight
long weight = 0;
while (data.length() > pos && isdigit(data.at(pos)))
weight = 10 * weight + data.at(pos++) - 48;
weight *= 2 << depth;
wantedList.push_back(weight);
return ++pos;
int doStuff(string data)
typedef map<long, int> Map;
vector<long> wantedList;
Map map;
read(data, 0, 0, wantedList);
for (long i : wantedList)
if (map.find(i) != map.end())
map[i] = map[i] + 1;
else
map[i] = 1;
vector<int> list;
for (Map::iterator it = map.begin(); it != map.end(); ++it)
list.push_back(it->second);
sort(list.begin(), list.begin() + list.size());
cout << wantedList.size() - list.back() << "\n";
return 0;
int main()
string data;
int i;
cin >> i;
for (int j = 0; j < i ; ++j)
cin >> data;
doStuff(data);
return 0;
我刚刚尝试了我的第一个 C++ 项目,它是用 Java 重写的代码。 最初的任务是计算需要更改多少数字才能“平衡”输入,假设高于某物的每一层的重量是低层的两倍
例如 [1,2] 需要 1 次更改(1->2 或 2->1 以便两边相等,而 [8,[4,2]] 需要 1 次更改(2-> 4)为了让“低级”变成8级,从而在高级上具有同等权重。有兴趣的可以在这里找到问题:
Problem link
对于那些想知道的人来说,这是关于算法的学校作业,但我不是在寻求帮助,因为我已经用 Java 完成了它。问题是我的算法在 C++ 方面似乎很糟糕。
在 Java 中,我得到大约 0.6 秒的时间,而在 C++ 中,“相同”代码给出 >2 秒(超出时间限制)。
有人愿意告诉我这是为什么吗?在处理这类问题时,我的印象是 C++ 应该比 Java 快。
【问题讨论】:
这可能更适合codereview 网站。也就是说,由于您是 C++ 新手,您是否打开了编译器优化? Java 默认启用它们,但对于 C++,您通常必须启用它们。data
有多大?你到处抄袭
你可能想通过引用传递你的字符串作为开始。
你根本不需要list
。您正在对map
中的所有值进行排序,然后取最大值。您可以简单地使用std::max_element
获得map
中的最大值。如果您不需要按键排序,也可以使用std::unordered_map
,这可能更好地反映您的 Java 代码。
@nikolap 哈哈,谢谢伙计!这将时间从 >2 缩短到 0.13
【参考方案1】:
可能的原因之一是复制。
每当您在 C++ 中按值传递某些内容时,都会创建一个副本。对于double
、int
或指针之类的东西,这不是问题。
但是对于像std::string
这样的对象,复制可能会很昂贵。由于您不修改 data
,因此通过 const 引用传递它是有意义的:
int read(const string &data, int depth, int pos, vector<long>& wantedList)
【讨论】:
以上是关于特拉亨伯格(Trachtenberg)速算(转载)的主要内容,如果未能解决你的问题,请参考以下文章
经验分享Trachtenberg system(特拉亨伯格速算系统)