快速幂+矩阵乘方

今天复习了一下快速幂, 又把长久以来未解决的那道矩阵的乘方解决了。好开心啊!

那么先来复习一下快速幂;

ep:1

这次题目很简单。给你一个整数N,求NN的个位数。

#include<stdio.h>
#include<math.h>
#define X 10
int main()
{
	int T,i,j,t,ans;
	__int64 n;
	int powermod(int a,int b);
	while(scanf("%d",&T)!=EOF)
	{
		for(i=1;i<=T;i++)
		{
			scanf("%I64d",&n);
			ans=powermod(n,n);
			printf("%d\n",ans);
		}
	}
	return 0;
}
int powermod(int a,int b){
	__int64 ans=1,pow=a;
	while(b!=0)
	{
		if(b&1) ans=(ans*pow)%X;
			pow=(pow*pow)%X;
			b=b/2;
	}
	return (int)ans;
}


 

ep2 :

给你两个数列:{Ai},{Bi},长度都为H,求(A1B1+A2B2+ ... +AHBH)mod M的值。

当然,作为学霸,杰哥不是不会做,而是太懒了。于是他又像聪明的程序员——你来求助了。请帮他快速算出该表达式的值。

#include<stdio.h>
int main()
{
	int T,i,j,m,h,a,b;
	__int64 sum;
	int powermod(int a,int b,int c);
	while(scanf("%d",&T)!=EOF)
	{
		for(i=1;i<=T;i++)
		{
			sum=0;
			scanf("%d",&m);
			scanf("%d",&h);
			for(j=1;j<=h;j++)
			{
				scanf("%d %d",&a,&b);
				sum+=powermod(a,b,m);
			}
			sum=sum%m;
			printf("%I64d\n",sum);
		}
	}
}
int powermod(int a,int b,int c)
{
	__int64 ans=1,pow=a;
	while(b!=0){
		if(b%2!=0) ans=(ans*pow)%c;
			pow=(pow*pow)%c;
			b/=2;
	}	
	return(int)ans;
}


 

所谓快速幂,就是不断地缩小问题,化为子问题。

当为奇数时,那么就先乘以原来的那个,因为当n是奇数时,肯定是只进行第一次的if条件里面的那个语句,后面的话应该都是偶数了。

若是偶数时,就pow进行自乘。

最终肯定会有个1,所以,ans乘进去后就是最终结果了。

 

那么,对于矩阵乘方来说也是可以化成这样的问题,只不过,最好把每次矩阵的相乘和快速幂的函数分开来写,这样会显得更清晰点。

ep 3:

yyf最近在学习线性代数。他发现可以用矩阵乘法来求解递推式。例如求解斐波那契数列。

先构造一个矩阵A

1 1

1 0

再用斐波那契数列的前两项f2 ,f1 构造一个矩阵B

1

1

A*B

可得

2

1

f3

f2

易知

(A^n)*B

可以得到一个

f(n+2)

f(n+1)

构成的矩阵

那么问题来了。

斐波那契数列第n项的值为多少

Input

输入第一个数字为样例组数T(T<=10000)

每组样例为一个数字n(n<=100000000)

Output

输出斐波那契数列的第n项值(输出的数字可能会比较大,输出结果对10007取余)

 

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
		
#define mod 10007
int n;
int sum[10][10],s[10][10];
void calutate(int a[10][10],int b[10][10]){
	int i,j,k;
	int c[10][10]={0};
	for(i=1;i<=2;i++)
		for(j=1;j<=2;j++)
			for(k=1;k<=2;k++){
				c[i][j]+=a[i][k]*b[k][j];
			}
	for(i=1;i<=2;i++)
		for(j=1;j<=2;j++)
		a[i][j]=c[i][j]%mod;
}
int Martix(int k){
	memset(sum,0,sizeof(sum));
	int i,j;
	//构造单位矩阵; 
	for(i=1;i<=2;i++) sum[i][i]=1;
	while(k!=0){
		if(k%2) calutate(sum,s);
			calutate(s,s);
		k=k/2;
	}
	int ans=0;
	ans=(sum[2][1]*1+sum[2][2]*1)%mod;
	return ans;
}
int main(){
		int T;
		cin>>T;
		while(T--){
			s[1][1]=1; s[1][2]=1;  s[2][1]=1;  s[2][2]=0;
			cin>>n;
			n=n-1;
			int ans=Martix(n);
			cout<<ans<<endl;
		}
}


一开始也是这样写的,但是不能输出,后来把int 中的sum的值改小了后就可以了,这里的原因不是十分清楚。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值