HDU 4990 矩阵快速幂

http://acm.hdu.edu.cn/showproblem.php?pid=4990

Read the program below carefully then answer the question.
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include<iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include<vector>

const int MAX=100000*2;
const int INF=1e9;

int main()
{
  int n,m,ans,i;
  while(scanf("%d%d",&n,&m)!=EOF)
  {
    ans=0;
    for(i=1;i<=n;i++)
    {
      if(i&1)ans=(ans*2+1)%m;
      else ans=ans*2%m;
    }
    printf("%d\n",ans);
  }
  return 0;
}

Input

Multi test cases,each line will contain two integers n and m. Process to end of file.
[Technical Specification]
1<=n, m <= 1000000000

Output

For each case,output an integer,represents the output of above program.

Sample Input

1 10
3 100

Sample Output

1
5

题目大意:给你一段代码,让你看,输入n和m让你输出结果。

思路:找规律可以发现F(n)=F(n-1)+2*F(n-2)+1。直接看图吧,然后就知道用矩阵快速幂了。第一次写这个,有点乱。

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
#include<iterator>
#define EPS 1e-12
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

ll n,m;
struct Matrix
{
	ll t[3][3];
	Matrix()
	{
		t[0][0]=t[0][1]=t[2][0]=t[2][2]=1;
		t[1][0]=2;
		t[0][2]=t[1][1]=t[1][2]=t[2][1]=0;
	}
};

Matrix mul(Matrix a,Matrix b);
Matrix qpow();

int main()
{
	while(~scanf("%lld%lld",&n,&m))
	{
		if(m==1)
			printf("0\n");
		else if(m==2)
		{
			if(n&1)
				printf("1\n");
			else
				printf("0\n");
		}
		else if(n==1)
			printf("1\n");
		else if(n==2)
			printf("2\n");
		else
		{
			Matrix a=qpow();
			Matrix b;
			b.t[1][0]=b.t[2][0]=b.t[2][2]=0;
			b.t[0][0]=2;
			b.t[0][1]=b.t[0][2]=1;
			a=mul(b,a);
			printf("%lld\n",a.t[0][0]);
		}
	}
	return 0;
}

Matrix mul(Matrix a,Matrix b)
{
	Matrix c;
	for(int i=0;i<3;i++)
		for(int j=0;j<3;j++)
			c.t[i][j]=0;
	for(int i=0;i<3;i++)
		for(int j=0;j<3;j++)
			for(int k=0;k<3;k++)
				c.t[i][j]=(c.t[i][j]+a.t[i][k]*b.t[k][j])%m;
	return c;
}

Matrix qpow()
{
	ll b=n-2;
	Matrix t1,t2;
	for(int i=0;i<3;i++)
		for(int j=0;j<3;j++)
		{
			t1.t[i][j]=(i==j?1:0);
		}
	while(b>0)
	{
		if(b&1)
			t1=mul(t1,t2);
		t2=mul(t2,t2);
		b/=2;
	}
	return t1;
}

补充:快速幂的原理是什么呢,其实就是利用了二进制数。比如我们要计算a^b,b可以用二进制数的形式表示出来,假设b=c1+c2+……+cn,那么a^b=(a^c1)*(a^c2)*……*(a^cn)。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值