hdu 2814 Interesting Fibonacci

本文详细解析了HDU2814 Interesting Fibonacci题目,介绍了如何利用斐波那契数列和指数循环节解决大规模数值计算的问题,并分享了多次调试过程中遇到的坑及解决方案。

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

题目:hdu 2814 Interesting Fibonacci

题意:求F(a^b)^(F(a^b) ^ (n-1))%c  (F(n)表示斐波那契数列,1<=c<=300,a,b,n都是2^64的数,用unsigned long long存)

思路:指数循环节和斐波那契数列循环节

我是不会跟你说这题我WA,TLE,RE了二三十次了。。。然后足足AC了七遍。。

F(n)%c 的情况,根据斐波那契数列的循环节求出来,做法跟12年四川现场赛那题一样。

式子中存在两个F(a^b) ,对于第一个,求对于mod c的循环节,第二个根据指数循环节,求mod phi(c)的循环节,然后其他就是乱七八糟的求快速幂,求斐波那契数列。

这题,TLE若干次之后,发现因为c的范围只有300,所以我们可以先预处理300以内数字的循环节。

然后,经历了若干次RE,原因是除0了(我除你妹的0,我压根就没粗线过0)。

意外的将题目数据改成17 18446744073709551615 1998 2程序直接跪了,看来问题在于 mod 2 的那,找了下别人的代码,试了这组数据,照样跪了,但是为喵别人能AC 呢 (之后我AC的代码输出的答案是 1)

所以呢,在经历无数次WA之后,貌似找到问题所在了,模1的情况答案输出当然是0,模2的暂时不知道,想一想欧拉值等于1的只有2,所以当c=2的时候,F的幂的部分就mod 1直接等于0,所以不管底数多少,答案就是1了,解释了我刚才说的样例。

然后对于前面的预处理 smod[1]=1 这个得加上(虽然我不知道什么时候会出现这种数据,但是不加这句话,就是会RE)


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
typedef unsigned __int64 LL;
struct Matrix
{
	LL m[3][3];
}E, D;
LL Pow(LL a, LL b, LL mod)
{
	LL ans = 1;
	while (b)
	{
		if (b & 1)
		{
			b--;
			ans = (ans*a)%mod;
		}
		else
		{
			b /= 2;
			a = (a*a)%mod;
		}
	}
	return ans;
}
void init()
{
	for (int i = 1; i <= 2; i++)
		for (int j = 1; j <= 2; j++)
		{
			D.m[i][j] = 1;
			E.m[i][j] = (i == j);
		}
		D.m[2][2] = 0;
}
Matrix Multi(Matrix A, Matrix B, LL mod)
{
	Matrix ans;
	for (int i = 1; i <= 2; i++)
		for (int j = 1; j <= 2; j++)
		{
			ans.m[i][j] = 0;
			for (int k = 1; k <= 2; k++)
				ans.m[i][j] = (ans.m[i][j] + A.m[i][k] * B.m[k][j])%mod;
		}
		return ans;
}
Matrix Pow(Matrix A, LL k, LL mod)
{
	Matrix ans = E;
	while (k)
	{
		if (k & 1)
		{
			k--;
			ans = Multi(ans, A, mod);
		}
		else
		{
			k /= 2;
			A = Multi(A, A, mod);
		}
	}
	return ans;
}
LL Fib(LL n, LL mod)
{
	return Pow(D, n, mod).m[2][1];
}
long long euler(long long x)
{
	long long i, res = x;
	for (i = 2; i*i <= x; i++)
		if (x%i == 0)
		{
			res = res / i*(i - 1);
			while (x%i == 0)
				x /= i;
		}
		if (x > 1)
			res = res / x*(x - 1);
		return res;
}
LL s_mod(LL n)
{
	LL a1 = 0, a2 = 1, a3 = 1, tmp, ans = 1;
	while (a2 != 0 || a3 != 1)
	{
		ans++;
		tmp = (a2 + a3)%n;
		a2 = a3;
		a3 = tmp;
	}
	return ans;
}
LL smod[305];

int main()
{
	init();
	smod[1] = 1;
	for (int i = 2; i <= 300; i++)
		smod[i] = s_mod(i);
	LL a, b, n;
	int c;
	int t;
	scanf("%d", &t);
	LL mod1, mod2, tmp, cnt, ans, eul;
	for (int cas = 1; cas <= t; cas++)
	{
		scanf("%I64u%I64u%I64u%d", &a, &b, &n, &c);
		if (c == 1)
		{
			printf("Case %d: 0\n", cas);
			continue;
		}
		mod1 = smod[c];
		eul = euler(c);
		mod2 = smod[eul];
		tmp = Pow(a%mod1, b, mod1);
		tmp = Fib(tmp, c);
		cnt = Pow(a%mod2, b, mod2);
		cnt = Fib(cnt, eul);
		cnt = Pow(cnt, n - 1, eul);
		cnt += eul;
		ans = Pow(tmp, cnt, c);
		printf("Case %d: %I64u\n", cas, ans);
	}
	//system("pause");
	return 0;
}


### 使用多种编程语言实现输出斐波那契数列的前四项 以下是几种常见编程语言实现输出斐波那契数列前四项的方法: #### C++ 实现 在C++中可以通过简单的循环来计算并打印斐波那契数列的前几项。 ```cpp #include <iostream> using namespace std; int main() { cout << "Fibonacci数列的前4项如下:" << endl; int a = 1, b = 1; // 初始化前两项 cout << a << " " << b << " "; // 打印前两项 for (int i = 1; i <= 2; ++i) { // 计算并打印后续两项 int nextTerm = a + b; cout << nextTerm << " "; a = b; b = nextTerm; } cout << endl; return 0; } ``` 此代码片段基于引用中的逻辑[^1],简化为仅输出前四项。 --- #### Python 实现 Python 提供了一种简洁的方式来生成斐波那契数列。通过列表推导或其他方法可轻松完成任务。 ```python def fibonacci_four_terms(): terms = [1, 1] # 初始两个值 for _ in range(2): # 添加接下来的两项 terms.append(terms[-1] + terms[-2]) return terms[:4] result = fibonacci_four_terms() print("Fibonacci数列的前4项:", result) ``` 上述代码利用了动态数组的概念,类似于引用中的描述[^2],但调整为了只生成四个数值。 --- #### Java 实现 Java 中可以借助 `ArrayList` 来存储和操作斐波那契序列。 ```java import java.util.ArrayList; public class FibonacciFourTerms { public static void main(String[] args) { ArrayList<Integer> fabList = new ArrayList<>(); fabList.add(1); fabList.add(1); for (int i = 2; i < 4; i++) { fabList.add(fabList.get(i - 1) + fabList.get(i - 2)); } System.out.println("Fibonacci数列的前4项:"); for (Integer num : fabList) { System.out.print(num + " "); } } } ``` 这段代码参考了 Java 的实现方式[^5],并对范围进行了修改以便适应当前需求。 --- #### C 实现 对于更基础的语言如C,则可以直接采用数组或者变量交换的方式处理。 ```c #include <stdio.h> void print_fibonacci_first_four() { int first = 1, second = 1; printf("%d %d ", first, second); // 输出前两项目 for(int i = 3; i <= 4; i++) { // 继续计算剩余部分直到第四项为止 int third = first + second; printf("%d ", third); first = second; second = third; } } int main(){ print_fibonacci_first_four(); return 0; } ``` 该版本遵循传统迭代模式构建结果集,并且保持简单明了结构设计思路来自其他例子[^3]^。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值