Number Sequence HDU - 1005 循环节

本文介绍了一种利用循环节求解大规模递推数列的方法,通过限制数列元素范围并寻找循环规律,实现了高效计算递推式第n项的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解

题目大意,给定一个递推式要求求出递推式的第n项,n <= 1e9。

题目是可以用矩阵快速幂直接log复杂度求出,但是麻烦啊。。所以以下代码使用找循环节的方法。
递推式由前两项构成,每项都进行%7运算,取模之后范围0~6共7种,前两项最多有7*7=49种组合。所以在49+49个范围内一定能找到循环节(可能是混循环)。
递推得到前200项目(少点也行)。枚举循环节开始位置i,循环节终点j,只判断三位如果三位都相等则必然出现循环。
最后将n减去循环出现位置i,对循环节长度取模输出对应项即可。

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 200;
int f[N];

int main()
{
#ifdef LOCAL
	//freopen("C:/input.txt", "r", stdin);
#endif
	int a, b, n;
	while (scanf("%d%d%d", &a, &b, &n), a || b || n)
	{
		f[1] = f[2] = 1;
		for (int i = 3; i < N; ++i)
			f[i] = (f[i - 1] * a + f[i - 2] * b) % 7;
		if (n < N)
		{
			cout << f[n] << endl;
			continue;
		}
		/*
		for (int i = 0; i < 47; ++i)
			printf("%d ", f[i + 1]);
		cout << endl;
		for (int i = 47; i < 47 * 2; ++i)
			printf("%d ", f[i + 1]);
		cout << endl;
		*/
		bool lop = 1;
		for (int i = 0; i < 50 && lop; ++i) //找到循环起点
			for (int j = i + 1; j < 100 && lop; ++j) //下一个循环节
			{
				int flag = 1;
				for (int k = 0; k < 3; ++k)
					if (f[i + k] != f[j + k])
						flag = 0;
				if (flag)
				{
					n = i + (n - i) % (i - j);
					printf("%d\n", f[n]);
					lop = 0;
				}
			}
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值