为什么是 n(n+1)/2 ?
n(n+1)/2是一个数列的元素两两运算后的不重复结果数。如图:

假如数列a = 1,2,3....n。那么该数列内的元素两两相乘,则会构建出上图中的表格,这个表格应该有n x n 个元素。
用程序写出来大概就是这样:
for (int i=; i<n; i++){
for (int j=; j<n; j++){
table[i][j] = a[i]*a[j];
}
}
这段程序准确的描述了我们手工填表的过程,填满整个表一共执行了n*n次操作,产生了一个n*n的结果集,当然也包含大量重复元素。
那么到底有多少重复元素呢? 其实可以通过跟踪整个运算流程来观察出其中的规律。
1.当i=1时, a1 * a1, a1*a2.....a1*an 一切正常。
2.当i=2时, a2 * a1, a2*a2.....a2*an 看到第一项了么,在第一步时已经计算过一次了。
3.当i=3时,a3 * a1, a3*a2, a3* a3....a3*an 第一项在i=1时计算过,第二项在i=2时计算过。
依次类推,可以发现,当i=n的时候,除了an * an 需要计算以外,其他项全都已经计算过了。
现在让我们来一次时光倒流:从i=n的时候开始,他只有最后一次计算是不重复的(an*an),其余n-1次运算都是"徒劳",所以它产生了n-1个重复元素。
然后是i=n-1的时候,他只有最后两次运算是不重复的(an-1 * an-1, an-1 * an),余下的n-2个计算结果都是重复的。
一直进行到当i=2的时候,也就是上面描述的第二步,当第一个重复数出现的时候。
然后就可以把他们都加起来,他们的和就是所有重复数了:r = 1+2+...+n-1
1 + 2 + ... + n-1 =r
2 n-1 + n-2 + ... + 1 =r
将1式和2式相加=> 2r = n(n-1) => r = n(n-1)/2
得到了重复数r,那么剩下多少不重复的呢? n*n - r = n(n+1)/2 wala~ QED
----Note---
这其实是一个可重复的N choose M 组合问题,而这里的M是2,有时间的话想好好证明一下这个问题
随机推荐
- JDBC的应用
JDBC的开发步骤: 1. 引入JDBC驱动架包 2. 程序中引入JDBC驱动类 3. 创建java与数据库的连接 4. 跟数据库交互:发送sql语句,接收数据库对sql语句的执行结果 ...
- 线程池大小 & cpu core
http://stackoverflow.com/questions/14556037/number-of-processor-core-vs-the-size-of-a-thread-pool ht ...
- phpcms常用方法简介
function thumb() /** * 生成缩略图函数 * @param $imgurl 图片路径 * @param $width 缩略图宽度 * @param $height 缩略图高度 * ...
- HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth之完全详解
HTML:scrollLeft,scrollWidth,clientWidth,offsetWidth到底指的哪到哪的距离之完全详解 scrollHeight: 获取对象的滚动高度. scrollLe ...
- Repository设计模式
definition: 通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调. advantage: 使用该模式的最大好处就是将领域模型从客户代码和数据映射层之间解耦出来. 理解内 ...
- poj 3268(spfa)
http://poj.org/problem?id=3268 对于这道题,我想说的就是日了狗了,什么鬼,定义的一个数值的前后顺序不同,一个就TLE,一个就A,还16MS. 感觉人生观都奔溃了,果然,题 ...
- Light OJ 1140
数位dp,需要记录前导0. 数位dp中需要注意统计0,00,000……这些数字. 数位dp的写法可以分为两类.由于我们通常采用记忆化搜索的方式进行dp,所以我们有一个记忆化数组. 一种是记忆化数组的意 ...
- shell 监控局域网的主机是否up
#!/bin/bash ;i<;i++)) ;do .$i>/dev/null #ping -c 172.31.0.30 ~172.31.0.59 ]] #if up $?==0 then ...
- FFmpeg-20160506-snapshot-bin
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 F ...
- linux 共享内存实现
说起共享内存,一般来说会让人想起下面一些方法:1.多线程.线程之间的内存都是共享的.更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享:2.父子进程间的内存共享 ...