xmu 1018 零零漆的作

Description

   世上没有铁饭碗裁员风也刮到了组织尽管零零漆为组织做了那么多贡献他还是得通过组织的素质能力以及水平测试才能继续他的特工工作凭他的经验以及高超的杀猪功力他顺利的通过了前面的测试来到了算法测试关给他的问题很简单----给两个整数n,m, 求斐波纳契数fib[n] % m...
算卖肉钱久了零零漆还真想不起怎么去计算斐波纳契数了但是他在考场竟然能通过安装在皮鞋里的电话和你通信他只能寄希望于你了...
当然你还是知道fib[n]的定义的:
/ fib[0]=0
| fib[1]=1
\ fib[n]=fib[n-1]+fib[n-2] (n>1)

Input

   输入第一行是一个整数 c, 0 < c <= 5000, 表示要计算多少个fib[n]
接下来的c每行有两个整数n,m, 0 <= n <= 2147483647, 0 < m < 32767, 意义如前所述

Output

   对于每对n,m, 对应输出单独的一行包含一个整数 r = fib[n] % m

Sample Input

8
42 8468
6335 6501
19170 5725
11479 9359
26963 4465
5706 8146
23282 6828
9962 492

Sample Output

3712
3547
1210
5683
1502
5894
5113
1

Source

xmu @ arxor @ alrale

 

首先这个题目是一类典型问题中的一个。就是用矩阵乘法解决加速状态转移。

现在我们需要构造一个2 x 2的矩阵,使得它乘以(fib[n-2],fib[n-1])得到的结果是(fib[n-1],fib[n-1]+fib[n-2])。每多乘一次这个矩阵,这两个数就会多迭代一次。那么,我们把这个2 x 2的矩阵自乘n次,再乘以(0,1)就可以得到第n个Fib数了不用多想,这个2 x 2的矩阵很容易构造出来:


具体分解一下就是如下步骤:


是不是瞬间明白什么了看完上面的分解步骤是不是豁然开朗了呢?

类似的问题matrix67有一篇非常不错的文章 看文戳这里

一段N年前的代码

#include<stdio.h>
int A,B,C,D,m;
void cal (int&a,int &b,int &c,int&d,int n)
{
	if (n>1)
	{
		if(n%2)
		{
			cal(a,b,c,d,n-1);
			A = (a+c)%m;
			B = (b+d)%m;
			C = a;
			D = b;
		}
		else
		{
			cal(a,b,c,d,n/2);
			A = (a*a+b*c)%m;
			B = (a*b+b*d)%m;
			C = (c*a+d*c)%m;
			D = (c*b+d*d)%m;
		}
			a = A;
			b = B;
			c = C;
			d = D;
	}
}
int main ()
{

	int a,b,c,d,n,T;
	scanf("%d",&T);
	while(T--)
	{	
	scanf("%d %d",&n,&m);
	n--;
	a =b =c =1;
	d =0;
	if(n)
	{
	cal(a,b,c,d,n);
	printf("%d\n",a%m);
	}
	else
		printf("0\n");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值