2676人阅读
昨天晚上看到了一道求解斐波那契数的编程题,里边介绍了通过矩阵来计算的办法。现将题摘录如下
Fibonacci数列是满足如下条件的整数数列:
FN = FN-1+FN-2 (N≥2)
Fibonacci数列的前10项如下:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
另一个求解Fibonacci数列的公式是:
对于任意给定的整数N,请求出FN模10000的余数。
输入包含多组测试数据。
每组数据占一行,仅包含一个整数n(0≤n≤1,000,000,000)最后一行为整数-1代表输入结束,不需要做处理。
对于每组测试数据,输出FN模10000的余数。
由于最近考研复习矩阵,所以看到了这个就眼前一辆,马上就想到了对角化等比较深奥的东西,,不过这里顺便引用我比较喜欢的一句话
Before you attain it, it is something
wonderful, but after you attain it, it is nothing special.
我觉得我现在已经到了nothing special的境界了。
言归正传,这题的思路想必大家都会,但是要将时间限制在5000ms估计就不是每个人都会的了。如何求一个矩阵的N次方呢,如果一个乘一个的话,很明显复杂度达到了O(N),昨天晚上编程一个多小时,发现无论如何都达不到要求,每次提交都会超时。无奈,今天还要早起学习,于是就去睡觉了。不过上天眷顾啊,当我躺下的那一刻,一道闪电划过夜空,我想到了二进制,于是所有的问题都解决了。
任何一个数n都可以表示成如下形式
n = x0 * 2^0 + x1*2^1 + x2*2^2 + ... + xj*2^j。推及矩阵也是一样的
于是我就设计了一个简单的数据结构
struct matrix{
int a11,a12,a21,a22;
并声明了一个数组
#define N 32
struct matrix matrix[N];
matrix[i]用于存储矩阵的2^i次方
所以对于任意n次方,只要从以上数组中找出有限个相乘即可得到***,复杂度变成了O(lg n)。^_^,是不是非常amazing啊。现在我就给出源代码,最多只要3ms就可以通过测试哦,不过我在那个测试列表中看到有些人只用了2ms,真的是人外有人啊,向大神们致敬!!!!!
#include &stdio.h&
#include &stdlib.h&
struct matrix{
int a11,a12,a21,a22;
#define N 32
struct matrix matrix[N];
void init_matrix(){
matrix[0].a11 = 1, matrix[0].a12 = 0, matrix[0].a21 = 0, matrix[0].a22 = 1;
matrix[1].a11 = 1, matrix[1].a12 = 1, matrix[1].a21 = 1, matrix[1].a22 = 0;
for(i = 2; i & N; i++){
matrix[i].a11 = ( matrix[i-1].a11 * matrix[i-1].a11 + matrix[i-1].a12 * matrix[i-1].a21 ) % 10000;
matrix[i].a12 = ( matrix[i-1].a11 * matrix[i-1].a12 + matrix[i-1].a12 * matrix[i-1].a22 ) % 10000;
matrix[i].a21 = ( matrix[i-1].a21 * matrix[i-1].a11 + matrix[i-1].a22 * matrix[i-1].a21 ) % 10000;
matrix[i].a22 = ( matrix[i-1].a21 * matrix[i-1].a12 + matrix[i-1].a22 * matrix[i-1].a22 ) % 10000;
void matrix_mul(struct matrix* s1, struct matrix* s2, struct matrix* d){ //s1,s2 and d must be different matrix pointer
d-&a11 = ( s1-&a11 * s2-&a11 + s1-&a12 * s2-&a21 ) % 10000;
d-&a12 = ( s1-&a11 * s2-&a12 + s1-&a12 * s2-&a22 ) % 10000;
d-&a21 = ( s1-&a21 * s2-&a11 + s1-&a22 * s2-&a21 ) % 10000;
d-&a22 = ( s1-&a21 * s2-&a12 + s1-&a22 * s2-&a22 ) % 10000;
struct matrix get_n_matrix(int n){ // n&=1
int i = 1;
struct matrix result = { .a11 = 1, .a12 = 0, .a21 = 0, .a22 = 1,};
if(n % 2 == 1){
matrix_mul(&result, &matrix[i], &temp);
int get_fn(int n){
if(n &= 1)
temp = get_n_matrix(n-1);
return temp.a11;
int main()
int n, result[N*N*N], k = 0,
init_matrix();
while(scanf(&%d&, &n) == 1){
if(n == -1)
result[k++] = get_fn(n);
for(i = 0; i & i++)
printf(&%d\n&, result[i]);
好好学习,天天向上!!!!!!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4551次
排名:千里之外阅读短文,回答问题:物质的粘性初春的早晨,小丽去农贸市场买蜂蜜,售货员将蜂蜜用勺子盛出,往瓶子里倒.小丽发现蜂蜜向下流动得比较缓慢,不像流水那样.走在回家的路上,她想到这样的问题:是否有什么因素使得蜂蜜的粘性有时大有时小呢?也就是说物质的粘性大小与什么因素有关呢?小丽大胆地提出了自己的假说:物质的粘性也可能与温度有关,温度越高,粘性越小.也就是说,如果让同一种液体从相同的斜面流下,温度低时需要的时间长,温度高时需要的时间短.小丽赶回家,设计了如下的实验方案:将蜂蜜分装入三个小瓶,一瓶放在冰箱,一瓶放在室内,另一瓶放在微波炉加热一会儿.然后找三支相同的试管,让爸爸妈妈帮忙,用三支滴管分别从三个小瓶中各取一滴蜂蜜,同时,分别滴到同样倾斜放置着的试管内壁上,如图19所示,观察各滴蜂蜜流到试管底部的时间并进行比较.在爸爸妈妈的帮助下,小丽顺利完成了实验,并记录实验数据如下:
在微波炉加热
较短小丽和爸爸妈妈一起又用其他几种物质做了相同的实验,并对这些实验现象进行了分析.小丽象科学家那样得出了结论,请你回答:(1)小丽得出的结论是:有些物质,随着温度的升高,它的粘性越小.(2)这一结论可以用下列的B图象来表示.(3)在上述探究过程中,小丽运用了转换法,通过这种科学方法,小丽将不能直接测量的粘性转换成可以测量的时间.(4)在上述探究过程中,小丽是按照怎样的思维程序进行探究的?答:发现问题→进行猜想→制定计划与设计实验→进行试验→分析与论证.
晓丽要探究粘性和温度的关系,温度可以用温度计来测量,但粘性是无法测量的,晓丽用了转换法,测出了它们流经同一斜面上的时间,从而显示出了粘性的大小.由表格我们可以很明显的得出粘性和温度的关系图象.探究实验包括:发现问题、猜想和假设、设计实验、进行实验、归纳分析、得出结论.(1)由记录表格可以发现,温度越高流淌时间越长,而流淌时间越长就说明物体的粘性越大,所以得出结论:有些物质,随着温度的升高,它的粘性减小.(2)这一结论可以用图B显示出来.温度升高时,粘性变小.(3)在相同的斜面上,相同的坡度,蜂蜜的流淌时间越长也就说明了蜂蜜的粘性越大.所以晓丽将不能直接测量的粘性转换为可以测量的时间.(4)晓丽经历的探究思维程序是:发现问题、设计实验、进行实验、归纳分析、得出结论.故***为:温度;越小;B;粘性;时间;发现问题;进行试验.