UVa 11582 Colossal Fibonacci Numbers!

题目链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2629


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n;

unsigned long long a, b;

// 计算p[i]为模i的周期
int p[1010];

// 计算f[i][j]为f(j) % i
int f[1010][1010*6];
// 计算f(x) % n 的前n^2+1项
//int f[1000010];
//int f[1010][1010];

// p[x][y] = i代表f(i)%n=x, f(i+1)%n=y
//int p[1010][1010];

// 循环的周期
int period;

long long get_result(unsigned long long x, unsigned long long y);


int main()
{
	p[1] = 1;
	for(int i = 2; i <= 1000; i++)
	{
		f[i][0] = 0, f[i][1] = 1;
		for(int j = 2; ; j++)
		{
			f[i][j] = (f[i][j-1] + f[i][j-2]) % i;
			if(f[i][j] == 1 && f[i][j-1] == 0)
			{
				p[i] = j-1;
				break;
			}
		}
	}
	int t;
	scanf("%d", &t);
	int count = 0;
	while(count < t)
	{
//		scanf("%lld %lld %d", &a, &b, &n);

		cin >> a >> b>> n;
/*
		memset(p, -1, sizeof(p));
		// 计算f(x) % n 的前n^2+1项
		int end = n*n+1;
		f[0] = 0;
		f[1] = 1 % n; 
		p[f[0]][f[1]] = 0;
		// 计算循环的周期
		period = -1;
		for(int i = 2; i <= end; i++)			
		{
			f[i] = (f[i-1]+f[i-2]) % n;

		//	printf("f[%d]: %d\n", i, f[i]);

			if(p[f[i-1]][f[i]] != -1 && period == -1)
			{
				period = i-1 - (p[f[i-1]][f[i]]);
//				printf("f[%d-1]: %d, f[%d]: %d\n", i, f[i-1], i, f[i]);
			}	
			p[f[i-1]][f[i]] = i-1;	
		}

//		int y = get_result(1, 0);
*/		
		if(a == 0 || n == 1)
			printf("0\n");
		else
		{
			int x = get_result(a % p[n], b);
			// 计算f[a^b % period]
			printf("%d\n", f[n][x]);
		}
		count++;	
	}	
	return 0;
}

// 计算x ^ y % period
long long get_result(unsigned long long x, unsigned long long y)
{
//	printf("x: %lld, y: %lld\n", x, y);
	if(y == 0)
	{
//		printf("here, period\n");
//		printf("%d\n", 1 % period);
		return 1 % p[n];
	}
	if(y % 2 == 0)	
	{
		int r1 = get_result(x, y/2);
		return (long long)(r1*r1) % p[n];
	}
	else 
	{
		int r1 = get_result(x, y/2);
		return (long long)(r1*r1*x) % p[n];
	} 			
}


主要障碍在计算f(a^b). 因为模n,结果最多n个数,前后两个数情况最多n^2. 所以必定存在循环。计算前n^2个数对,找到循环。

注意点:

1. 64位正整数,只能用unsigned long long 而不是long long. 只能用cin,而不是scanf.

2. 能打表先打表算好


没搞清的疑问(参考代码:https://github.com/aoapc-book/aoapc-bac2nd/blob/master/ch10/UVa11582.cpp):

1. 明明是最多前n^2个数,为何f第二维可以只开到6n?

2. 为何循环必定是和f(0),f(1)相同?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值