【矩阵乘法】Fibonacci数列 WikiOI 1732/1250

WikiOI 1732/1250 Fibonacci数列

题目描述Description

在“1250 Fibonacci数列”中,我们求出了第n个Fibonacci数列的值。但是1250中,n<=109。现在,你的任务仍然是求出第n个Fibonacci数列的值,但是注意:n为整数,且1 <= n <= 100000000000000

输入有多组数据,每组数据占一行,为一个整数n(1 <= n <= 100000000000000)

输出若干行。每行输出第(对应的输入的)n个Fibonacci数(考虑到数会很大,mod 1000000007)

3
4
5

 

2
3
5

 

1 <= n <= 100000000000000






这一题是1250的加强版,就合在一起写了


不过注意一点,1250是从0下标开始,这一题1732是从1下标开始


第一次写矩阵乘法,1250就1A了

然后就高高兴兴改了输入,交1732,结果WA了,还只有10分!!!改了好久20分,又改,又改,80分,终于A了

中间遇到的错误点

1.读入的 n 是 long long
2.快速幂x^y,其中 y 为 long long
3.矩阵乘法每次都要去mod


测评情况(WikiOI)


C++ AC Code(1732)

/*http://blog.csdn.net/jiangzh7
By Jiangzh*/
#include<cstdio>
#include<cstring>
const int mod=1000000007;
long long n;
struct Matrix{
	long long c[5][5];
	Matrix operator * (Matrix b)
	{
		Matrix res;
		res.c[1][1]=c[1][1]*b.c[1][1]%mod+c[1][2]*b.c[2][1]%mod;
		res.c[1][2]=c[1][1]*b.c[1][2]%mod+c[1][2]*b.c[2][2]%mod;
		res.c[2][1]=c[2][1]*b.c[1][1]%mod+c[2][2]*b.c[2][1]%mod;
		res.c[2][2]=c[2][1]*b.c[1][2]%mod+c[2][2]*b.c[2][2]%mod;
		return res;
	}
	Matrix getans(Matrix b)
	{
		Matrix res;
		res.c[1][1]=c[1][1]*b.c[1][1]%mod+c[1][2]*b.c[2][1]%mod;
		res.c[2][1]=c[2][1]*b.c[1][1]%mod+c[2][2]*b.c[2][1]%mod;
		return res;
	}
	Matrix operator % (int mod)
	{
		c[1][1]%=mod;c[1][2]%=mod;
		c[2][1]%=mod;c[2][2]%=mod;
		return *this;
	}
};

Matrix mul(Matrix x,long long y,int mod)
{
	if(y==1) return x;
	if(y&1) return mul(x*x%mod,y/2,mod)%mod*x;
	else return mul(x*x%mod,y/2,mod)%mod;
}

long long calc()
{
	n--;
	if(n==1||n==0) return 1;
	Matrix a;
	a.c[1][1]=a.c[1][2]=a.c[2][1]=1;
	a.c[2][2]=0;
	a=mul(a,n-1,mod);
	Matrix b; b.c[1][1]=b.c[2][1]=1;
	a=a.getans(b);
	return a.c[1][1]%mod;
}

int main()
{
	freopen("1732.in","r",stdin);
	freopen("1732.out","w",stdout);
	while(scanf("%lld",&n)==1)
		printf("%lld\n",calc());
	return 0;
}



C++ AC Code(1250)

/*http://blog.csdn.net/jiangzh7
By Jiangzh*/
#include<cstdio>
#include<cstring>

int n,mod;
struct Matrix{
	long long c[5][5];
	Matrix operator * (Matrix b)
	{
		Matrix res;
		res.c[1][1]=c[1][1]*b.c[1][1]+c[1][2]*b.c[2][1];
		res.c[1][2]=c[1][1]*b.c[1][2]+c[1][2]*b.c[2][2];
		res.c[2][1]=c[2][1]*b.c[1][1]+c[2][2]*b.c[2][1];
		res.c[2][2]=c[2][1]*b.c[1][2]+c[2][2]*b.c[2][2];
		return res;
	}
	Matrix getans(Matrix b)
	{
		Matrix res;
		res.c[1][1]=c[1][1]*b.c[1][1]+c[1][2]*b.c[2][1];
		res.c[2][1]=c[2][1]*b.c[1][1]+c[2][2]*b.c[2][1];
		return res;
	}
	Matrix operator % (int mod)
	{
		c[1][1]%=mod;c[1][2]%=mod;
		c[2][1]%=mod;c[2][2]%=mod;
		return *this;
	}
};

Matrix mul(Matrix x,int y,int mod)
{
	if(y==1) return x;
	if(y&1) return mul(x*x%mod,y/2,mod)%mod*x;
	else return mul(x*x%mod,y/2,mod)%mod;
}

long long calc()
{
	if(n==1||n==0) return 1;
	Matrix a;
	a.c[1][1]=a.c[1][2]=a.c[2][1]=1;
	a.c[2][2]=0;
	a=mul(a,n-1,mod);
	Matrix b; b.c[1][1]=b.c[2][1]=1;
	a=a.getans(b);
	return a.c[1][1]%mod;
}

int main()
{
	freopen("1250.in","r",stdin);
	freopen("1250.out","w",stdout);
	int T; scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&mod);
		printf("%lld\n",calc());
	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值