hdu 5667Sequence

Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 144    Accepted Submission(s): 46


Problem Description
     Holion August will eat every thing he has found.

     Now there are many foods,but he does not want to eat all of them at once,so he find a sequence.

fn=1,ab,abfcn1fn2,n=1n=2otherwise

     He gives you 5 numbers n,a,b,c,p,and he will eat fn foods.But there are only p foods,so you should tell him fn mod p.
 

Input
     The first line has a number,T,means testcase.

     Each testcase has 5 numbers,including n,a,b,c,p in a line.

    1T10,1n1018,1a,b,c109 , p is a prime number,and p109+7 .
 

Output
     Output one number for each case,which is fn mod p.
 

Sample Input
  
  
1 5 3 3 3 233
 

Sample Output
  
  
190
 

Source
BestCoder Round #80


思路:通过递推可以知道fn 都可以用f2 的多少次幂来表示,而幂的递推公式为an = (an - 1)* c + 1 +an - 2;因为n很大,所以用矩阵快速幂来算,

C  1  0

1  0  0                                                  【 an - 1,  an - 2,  1】       

1 0   1


前面的矩阵的n - 3次幂在乘以后面的矩阵,第一个值就是答案

要注意的是 a ^ b % c = a ^(b % phi(c) + phi(c)) % c; 因为c是质数,所以这里的phi就为c - 1;所以只要用矩阵幂的时候% c -1,答案% c即可。





#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
#define esp  1e-8
const double PI = acos(-1.0);
const int inf = 1000000005;
//const long long mod = 1000000007;
//freopen("in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
struct Mat
{
	long long mat[10][10];
}a, b, ans;
long long mod, eul;
Mat operator * (Mat a, Mat b)
{
	Mat c;
	memset(c.mat, 0, sizeof(c.mat));
	for (int k = 0; k < 3; ++k)
	{
		for (int i = 0; i < 3; ++i)
		{
			if (a.mat[i][k] == 0)
				continue;
			for (int j = 0; j < 3; ++j)
			{
				if (b.mat[k][j] == 0)
					continue;
				c.mat[i][j] = (a.mat[i][k] * b.mat[k][j] % eul + c.mat[i][j]) % eul;
				//c.mat[i][j] %= mod;
			}
		}
	}
	return c;
}
Mat power(Mat a, long long k)
{
	Mat res = ans;
	while (k)
	{
		if (k & 1)
			res = res * a;
		k >>= 1;
		a = a * a;
	}
	return res;
}
long long n, aa, bb, cc, p;
long long power1(long long a, long long b)
{
	long long res = 1;
	while (b)
	{
		if (b & 1)
			res = res * a % mod;
		b >>= 1;
		a = a * a % mod;
	}
	return res % mod;
}
long long eular(long long n)
{
	long long res = n, x = n;
	for (long long i = 2; i * i <= n; ++i)
	{
		if (x % i == 0)
			res = res * (i - 1) / i;
		while (x % i == 0)
			x /= i;
	}
	if (x > 1)
		res = res * (x - 1) / x;
	return res;
}
int main()
{
	int t, i, j;
	memset(ans.mat, 0, sizeof(ans));
	ans.mat[0][0] = ans.mat[1][1] = ans.mat[2][2] = 1;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%I64d%I64d%I64d%I64d%I64d", &n, &aa, &bb, &cc, &mod);
		long long f2 = power1(aa, bb);
		if (n == 1)
		{
			printf("1\n");
			continue;
		}
		if (n == 2)
		{
			printf("%I64d\n", f2);
			continue;
		}
		p = mod;
		eul = eular(mod);
		memset(a.mat, 0, sizeof(a.mat));
		a.mat[0][0] = cc;
		a.mat[0][1] = a.mat[1][0] = a.mat[2][0] = a.mat[2][2] = 1;
		b = power(a, n - 3);
		long long s = (b.mat[0][0] * (cc + 1) % eul + b.mat[1][0] * 1 % eul+ b.mat[2][0]) % eul;
	
		printf("%I64d\n", (power1(f2, s + eul)) % mod);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值