2016沈阳C - Recursive sequence

在这里插入图片描述

Sample Input

2
3 1 2
4 1 10

Sample Output

85
369

Hint

In the first case, the third number is 85 = 21十2十3^4.
In the second case, the third number is 93 = 2
1十1*10十3^4 and the fourth number is 369 = 2 * 10 十 93 十 4^4.

思路: 矩阵乘法,构建矩阵有点难度,推出公式
F(n) = 2 * F(n - 2) + F(n - 1) + (n + 1)^4
然后单纯F(n + 1), F(n), F(n - 1)不能构建矩阵,需要将里面的所有变量都列出
F(n)
F(n - 1)
(n + 1) ^ 4
(n + 1) ^ 3
(n + 1) ^ 2
(n + 1)
1
然后计算之间关系,构建矩阵(直接看代码里吧)
这题最难受的是我的数组开大了,导致我时间复杂度直接上了10倍,TLE了两发·······在初始化矩阵时。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>

using namespace std;

typedef long long ll;

const int N = 10;
ll n, p;
const ll mod = 2147493647;
ll a, b;

struct node {
	ll g[N + 2][N + 2];//结构体存储矩阵
}f, res, s, rans;

//构造单位矩阵
void matrixI(node& x)
{
	for (int i = 1; i <= N; ++i)
		for (int j = 1; j <= N; ++j)
		{
			if (i == j)x.g[i][j] = 1LL;
			else x.g[i][j] = 0LL;
		}
}

//矩阵乘法
void matrixMultiple(node& x, node& y, node& z)
{
	memset(z.g, 0, sizeof(z.g));

	for (int i = 1; i <= N; ++i)
		for (int j = 1; j <= N; ++j)
			for (int k = 1; k <= N; ++k)
			{
				z.g[i][k] += (x.g[i][j] * y.g[j][k]) % mod;
				if (z.g[i][k] >= mod)z.g[i][k] %= mod;
			}
}

//快速幂
void matrixMuli(ll k)
{
	matrixI(res);

	node tmp = f, t;

	while (k)
	{
		if (k & 1)
		{
			matrixMultiple(res, tmp, t);
			res = t;
		}
		matrixMultiple(tmp, tmp, t);
		tmp = t;
		k >>= 1;
	}
}

void init()
{
	f.g[1][1] = 1; f.g[1][2] = 2; f.g[1][3] = 1;
	f.g[2][1] = 1;
	f.g[3][3] = 1; f.g[3][4] = 4; f.g[3][5] = 6; f.g[3][6] = 4; f.g[3][7] = 1;
	f.g[4][4] = 1; f.g[4][5] = 3; f.g[4][6] = 3; f.g[4][7] = 1;
	f.g[5][5] = 1; f.g[5][6] = 2; f.g[5][7] = 1;
	f.g[6][6] = 1; f.g[6][7] = 1;
	f.g[7][7] = 1;
}

ll solve()
{
	ll ans;

	if (n == 1)
		ans = a % mod;
	else if (n == 2)
		ans = b % mod;
	else
	{
		matrixMuli(n - 2);
		ans = (s.g[1][1] * res.g[1][1] % mod + s.g[2][1] * res.g[1][2] % mod + s.g[3][1] * res.g[1][3] % mod + s.g[4][1] * res.g[1][4] % mod + s.g[5][1] * res.g[1][5] % mod + s.g[6][1] * res.g[1][6] % mod + s.g[7][1] * res.g[1][7] % mod) % mod;
	}

	return ans;
}

int main()
{
	ll t;
	scanf("%lld", &t);

	init();

	while (t--)
	{
		scanf("%lld%lld%lld", &n, &a, &b);

		//memset(f.g, 0, sizeof(f.g));
		//memset(res.g, 0, sizeof(res.g));
		//memset(s.g, 0, sizeof(s.g));
		//memset(rans.g, 0, sizeof(rans.g));

		s.g[1][1] = b;
		s.g[2][1] = a;
		s.g[3][1] = 3 * 3 * 3 * 3;
		s.g[4][1] = 3 * 3 * 3;
		s.g[5][1] = 3 * 3;
		s.g[6][1] = 3;
		s.g[7][1] = 1;

		ll ans = solve();

		printf("%lld\n", ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值