郭姐散步(二)(矩阵快速幂模板题)

00013:郭姐散步(二)

总时间限制

10000ms

 

内存限制

32768kB

描述

The first lady of our team is GuoJie, GuoJie likes walking very much.

Today GuoJie walks from the original point (0, 0), everytime he(may beshe?) can go up or left or right a step.

But she can't go back the point where she have visited.

For example, if he goes up a step, she will be at (1, 0) and she nevercomes back the point.

Now, if she can walk n(n <= 1e18) steps, can you find howmany ways she can walk? the result mod 1e9 + 7.

 

输入

There will be T (T <= 100000) cases,each case will input a n.

输出

For each group of input integers youshould output how many ways GuoJie can walk in one line, and with one line ofoutput for each line in input.

样例输入

1

2

样例输出

7


这道题目其实规律早就找出来了,数据量小的时候直接用递推式也可以做,但是这道题T和n都很大,所以要多加注意才行。

直接用递推式,要想推到1e18,实在是不大可能。所以这道题的正解是用矩阵快速幂。

矩阵快速幂应用的条件就是有递推式的时候,我们就必定可以转化为矩阵乘法来表示。

按照矩阵快速幂的原理,他会在n转化为二进制的为1的地方进行一次乘法。那么1e18,最多也就是2的63次方,也就是我们只需要进行63次运算即可得到答案,是不是很快呢?比直接用递推式算到1e18不知道快了多少倍。

由于这道题目T很大,达到了10万次,代码中有一个地方写不好的话,都有可能会被卡常,所以这是要注意的。

代码如下:

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream> 
using namespace std;

const long long mod = 1e9+7;

struct matrix
{
    long long a[2][2];
}origin,res;

matrix multiply(matrix x,matrix y)
{
	matrix temp;
	memset(temp.a,0,sizeof(temp.a));
	for(int i=0;i<2;i++)
		for(int j=0;j<2;j++)
			for(int k=0;k<2;k++)
				temp.a[i][j] = (temp.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
    return temp;
}

void init()
{
//	memset(res.a,0,sizeof(res.a));
	res.a[0][0] = 3;
	res.a[0][1] = 1;
	res.a[1][0] = 0;
	res.a[1][1] = 0;
//	memset(origin.a,0,sizeof(origin.a));
	origin.a[0][0] = 2;
	origin.a[0][1] = 1;
	origin.a[1][0] = 1;
	origin.a[1][1] = 0;
}

void calc(long long n)
{
	while(n)
	{
		if(n & 1)
			res = multiply(res, origin);
		n >>= 1;
		origin = multiply(origin, origin);
	}
	printf("%lld\n", res.a[0][0]);
}

int main()
{
	int T;
	long long N;
	scanf("%d",&T);
    while(T--)
    {
    	scanf("%lld", &N);
		init();
		if(N <= 0) 
			printf("0\n");  
		else if(N == 1)
			printf("3\n");
		else
			calc(N - 1);
    }
    return 0;
}

在矩阵乘法那里有一个乘法运算,为了防止乘法运算后再加上矩阵自己本身爆long long范围,其实应该用a * b % mod = ((a % mod) * (b % mod)) % mod,但是想了想,相对于long long而言,1e9+7其实是一个很小的数字,所以并不会爆long long才对。于是没有那上面那规律,直接写,也能过。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值