51nod 1126 求递推序列的第N项(构造矩阵或规律)

1126 求递推序列的第N项

基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题

有一个序列是这样定义的:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.

给出A,B和N,求f(n)的值。

Input

输入3个数:A,B,N。数字之间用空格分割。(-10000 <= A, B <= 10000, 1 <= N <= 10^9)

Output

输出f(n)的值。

Input示例

3 -1 5

Output示例

6

思路:

1.设X矩阵为 X = \begin{bmatrix} A &B \\ 1&0 \end{bmatrix},Y=\begin{bmatrix} f(2) &0 \\ f(1)&0 \end{bmatrix},可得X*Y=\begin{bmatrix} f(3)&0 \\ f(2)& 0 \end{bmatrix},归纳可得X^(n-2) * Y =\begin{bmatrix} f(n) &0 \\ f(n-1)& 0 \end{bmatrix}。其中X^(n-2)可由矩阵快速幂运算,由于Y中f(2)=1,f(1)=1,我们不必再去乘Y矩阵,输出时直接输出(X[0][0]+X[0][1])%7,相当于乘以Y矩阵。把矩阵快速幂运算模板改一下就好了。

2.由于是mod7的关系,只有0,1,2,3,4,5,6这7种状态,且f(1)=f(2)=1,所以f(n)的值是循环分布的。只要当f(i-1)=f(i)=1出现时就有了循环节,和f(1)=f(2)=1一样。找出循环节的长度也就是找出了规律。可见循环节最长为7*7=49.因为,一个f()的状态有7种,连续的二个f()组合就是7*7=49,此时会出现f(i-1)=f(i)=1。

思路1:

//矩阵幂运算 
#include<stdio.h>
#include<string.h>
using namespace std;
#define data 7
struct mat{
	long long a[2][2];
};
mat mat_return(mat x,mat y){
	mat res;
	memset(res.a ,0,sizeof(res.a));
	for(int i=0;i<2;i++)
	for(int j=0;j<2;j++)
	for(int k=0;k<2;k++)
	{
		res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j]%data)%data;
	}
	return res;
}
int main()
{
	long long n,A,B;
	scanf("%lld%lld%lld",&A,&B,&n);
		n-=2;
		mat c,res;
		c.a[0][0]=A,c.a[0][1]=B,c.a[1][0]=1,c.a[1][1]=0;//构造的矩阵 
		memset(res.a,0,sizeof(res.a));
			for(int i=0;i<2;i++)
			res.a[i][i]=1;//单位矩阵 ,都一样 
			while(n>0){//接下来就类似快速幂运算了 
				if(n&1)
				res=mat_return(res,c);
				c=mat_return(c,c);
				n/=2;
			}
			printf("%lld\n",(res.a[0][1]+res.a[0][0]+7)%7); 
		return 0;
	}

思路2:

#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 7
#define ll long long
ll f[50];
int main()
{
	ll a,b,n,i;
	scanf("%lld%lld%lld",&a,&b,&n);
	f[1]=f[2]=1;
	for(i=3;i<50;i++) {
		f[i]=((a*f[i-1]+b*f[i-2])%mod+mod)%mod;
		if(f[i-1]==1&&f[i]==1)
		{
			break;
		}
	}
	i-=2;f[0]=f[i];
	printf("%lld %lld\n",f[n%i],i);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值