开锁的经验大家都有,但是眼前这把锁不太好开,我们看看它
1 3 5 ( )
1 4 9 ( )
5 8 13 ( )
… … … ( )
1 4 9 ( )
5 8 13 ( )
… … … ( )
凭借你多年的开锁经验,你马上断定眼前这扇门用的是密码锁。只见锁身上有 n行数字,在每行数字末尾都有好几个数字拨盘。看着这一行行多少不一的数字和数字末尾留下的空格,你忽然想起了小时候经常玩的一个游戏:找规律。这个游戏就是给你一个数列的前几项,让你填出后一项,例如: 2 4 6 ( 8 ) 1 4 9 ( 16 )
在玩游戏的过程中,你发现了一个窍门,所有这类问题,都可以用这种方法解决:对于一个已知前 m项的数列 al , a2 , a3,…,am,一定可以找到惟一一个不超过m-1次的多项式f(x),使得 f ( l ) = a1 , f ( 2 ) = a2… f ( m ) = am,那么 f ( m + 1)就是要找的下一项。
现在你决定用这种方法试着打开眼前这把密码锁。
到这里,我们都想到了初中学的数列知识,但是如果数字很多的话,也就是问题的规模变大的话,我们是不是就只能等着知道密码的人来开锁了呢?
等知道密码的人来开锁的确是个不错的主意,但是这样的话偶也就不用发这个帖子了。(暂时还不清楚blog的文章应该叫什么,汗……)我们先看一下这个数列的通项公式:
![通项公式](http://blog.csdn.net/images/blog_csdn_net/richard_ma/PasLock.gif)
常理告诉我们,按照通项公式向后推出后面的项是解决问题最直接的方法,但是耗时耗力,很不划算。现在请出我们解决这个问题的英雄,其实是一个数学定理:如果一个数列的通项公式是关于自然数 n 的 r 次多项式,那么这个数列是r阶等差数列。(这个好像说得挺晕的)我们把它的思路清理一下,先给大家看一张图:
![数组拆解实例](http://blog.csdn.net/images/blog_csdn_net/richard_ma/PasLock1.gif)
这里的原数列是指密码锁上提供的线索,顺藤摸瓜是我们常用的手段。(这里以1,4,9的密码线索作为样例)首先,我们要不断的求数列中前后两项的差,然后用这些差构成一个新的数列。这就得到了1阶等差数列,由此方法得到2阶等差数列,一直到得到r阶等差数列(就像这里的2阶等差数列)。我们出这样的计算方法使得没进行一轮的求差,数列元素的个数就会减少一个,当我们把数列处理为只有一个元素时,我们要的自然数n就出现了,而且它是常数列,由此我们的下一项也就有据可查了。按照图中蓝色箭头所指的方向,我们可以把这里的2阶等差数列的最后面的2加上上一层的最后的元素,从而得到上一层的后一项,依照同样的方法,我们可以推出元数列的后一项。至此,我们就把密码锁解开了。
但是这个方法仅仅适用于r阶等差数列,那么我们如何判断任意给定的一个数列是否为r阶等差数列呢?
这又是一个难于回答的问题,我们如果按照通项公式去推的话,和直接用同项公式去做也就没什么区别了;如果我们假定它是r阶等差数列而直接用上述方法去做的话,工作量也会很大。我进行了多次的数据测试后发现,如果一个数列是由等差数列的元素经过相同的变换构造而成的话,这个数列的后一项就可以用上述方法求解,换而言之,就是r阶等差数列。
关于判断数列是否为r阶等差数列的问题我也是通过大量的数据试验得到的,并没有严格的数学理论支持,我希望看过这篇文章的朋友能帮我找到数学的理论支持。
最后附上我的JAVA源代码:
这个是PasLock.java
/**
*Name:PasLock.java
*Author:Richard
*Date:Apr-17,2006
*Version:1.0.0.0
*=================
*
*/
public class PasLock{
protected long result;
/**
*construct method
*/
public PasLock(){
result = 0;
}
/**
*
*/
public long r_cal(long num[]){
int m = num.length;
for(int j=m-1; j>0; j--)
for(int k=0; k<=j-1; k++)
num[k] = num[k+1]-num[k];
for(int j=0; j<m; j++)
result = result+num[j];
return result;
}
};
//==========End Class PasLock==========
这个是PasLockTest.java
/**
*Name:PasLockTest.java
*Author:Richard
*Date:Apr-17,2006
*Version:1.0.0.0
*=====================
*Test the class PasLock
*/
public class PasLockTest{
public static void main(String args[]){
long num[] = {5, 8, 13};
PasLock resultOfLock = new PasLock();
System.out.println("result of lock is " +resultOfLock.r_cal(num));
}
}
这个是PasLock.java
/**
*Name:PasLock.java
*Author:Richard
*Date:Apr-17,2006
*Version:1.0.0.0
*=================
*
*/
public class PasLock{
protected long result;
/**
*construct method
*/
public PasLock(){
result = 0;
}
/**
*
*/
public long r_cal(long num[]){
int m = num.length;
for(int j=m-1; j>0; j--)
for(int k=0; k<=j-1; k++)
num[k] = num[k+1]-num[k];
for(int j=0; j<m; j++)
result = result+num[j];
return result;
}
};
//==========End Class PasLock==========
这个是PasLockTest.java
/**
*Name:PasLockTest.java
*Author:Richard
*Date:Apr-17,2006
*Version:1.0.0.0
*=====================
*Test the class PasLock
*/
public class PasLockTest{
public static void main(String args[]){
long num[] = {5, 8, 13};
PasLock resultOfLock = new PasLock();
System.out.println("result of lock is " +resultOfLock.r_cal(num));
}
}