UVA 10870 Recurrences 矩阵快速幂

看题传送门:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1811

题目大意:

f(n) = a1 f(n- 1) + a2 f(n- 2) + a3 f(n-3) + ... + ad f(n- d), for n > d

你的任务是计算f(n)/m的余数

输入第一行为3个整数d,n,m

第二行为d个非负整数a1~d

第三行为d个非负整数f(1)~f(d)

 

嗯哼,我的数据结构的作业报告写了想提高的可以去切掉这题,星期四貌似要上去讲。总不能自己没A把,于是晚上A掉这题。不做死就不会死啊T T

傻B了一回,敲太快没结束条件,一直RE。然后以为是数组开太小又觉得不对啊。。。发现了之后习惯的写EOF。。。T T结束条件是3个0.。。笨蛋。。。。

 

言归正传,先简单的来。这也是我数据结构上次的作业

已知式子:F(n)=A*F(n-1)+B*F(n-2)(n>=2且 n 为整数)

输入第一行三个正整数 N,A 和 B(N<=10;1<=A、B<=100 且均为整数)。

接下来有 N 行,每行一个自然数 n(n<=100000000)。输出一行一个整数 F(n)结果对2013取模

输入

5 4 5

2

4

8

16

32

输出:

9
209
1377
182
9

输入:

2 100 100

10000000

100000000


输出:

1189

1585


以下直接复制我的结题报告:

 

UVA 10870 Recurrences 矩阵快速幂_第1张图片

UVA 10870 Recurrences 矩阵快速幂_第2张图片

(PS :PPT2013改成2003的格式这些公式都用图片保存。。。。。。T T.....可以复制文字了)

我们知道,计算机中用二进制来表示一个数。

如134的二进制为10000110

A^4能通过(A^2)*(A^2)得到,A^8又能通过(A^4)*(A^4)得到。

而A^134=(A^2)(A^4)(A^128)

可以根据这样的原理写出如下程序:

while(N>0)
 {
                if(N&1)
                       res=res*A;
                n>>=1;
                A=A*A;
 }


>>表示右移运算。什么?你不知道什么是右移?

>>:低位溢出,符号位不变,并用符号位补溢出的高位。

什么意思?

比如刚才说的134的二进制为10000110,考虑符号位的话就是0 10000110。(正数)

右移一次后就变为001000011

那么N& 1的意思是?

&运算代表逻辑与,是按位操作的。(很熟悉&&吧)

1的二进制前面都是0,最后一位是1,也就是说,当且仅当A最后一位是1时候,执行表达式。

我们知道,右移一次,该数/2

故执行A*A

下面来看看A^134次方是怎么计算的。

为了方便叙述,符号位不写。。。。正数么。。都是0

10000110

执行if(N&1)判断为假,移位一次变为 1000011 此时A为原来的2次方

执行if(N&1)判断为真,执行一次res=A^2,移位100001 此时A为原来的4次方

执行if(N&1)判断为真,执行一次res=(A^2)(A^4),移位10000 此时A为原来的8次方

执行if(N&1)判断为假,移位一次变为 1000 此时A为原来的16次方

执行if(N&1)判断为假,移位一次变为 100   此时A为原来的32次方

执行if(N&1)判断为假,移位一次变为 10 此时A为原来的64次方

执行if(N&1)判断为假,移位一次变为 1 此时A为原来的128次方

执行if(N&1)判断为真,执行一次res==(A^2)(A^4)(A^128)移位一次变为0(前面符号位补最高位)此时A为原来的256次方

判断条件while(n>0) 不满足退出循环。

这就是整体的过程。希望能帮助到你。

好了 贴上这题的代码:

 
            //重改了一下,优化可读性。
#include<cstdio>
const int mod=2013;

struct  Matrix
{
	int a[2][2];

	Matrix & operator *(const Matrix &b)
	{
		Matrix c;  
	
		c.a[0][0]=(a[0][0]*b.a[0][0] % mod  +	a[0][1]*b.a[1][0] % mod) %mod;
		c.a[0][1]=(a[0][0]*b.a[0][1] % mod  +	a[0][1]*b.a[1][1] % mod) %mod;
		c.a[1][0]=(a[1][0]*b.a[0][0] % mod  +	a[1][1]*b.a[1][0] % mod) %mod;
		c.a[1][1]=(a[1][0]*b.a[0][1] % mod  +	a[1][1]*b.a[1][1] % mod) %mod;	
		
		*this=c;
		return *this;
	}


}a;

void myPow(int n)        
{  
	Matrix b;

	//单位矩阵
	b.a[0][0]=1;
	b.a[0][1]=0;
	b.a[1][0]=0;
	b.a[1][1]=1;

	while(n>0)
	{
		if(1&n)
			b=b*a;

		a=a*a;
		n>>=1;
	}

	a=b;
}  

int main()
{
	int N,A,B;
	scanf("%d%d%d",&N,&A,&B);	

	while(N--)
	{
		int n;
		scanf("%d",&n);
		if(n==1||n==0)
			printf("1\n");
		else
		{	
			a.a[0][0]=A;
			a.a[0][1]=B;
			a.a[1][0]=1;
			a.a[1][1]=0;

			myPow(n-1);
			printf("%d\n",(a.a[0][0] + a.a[0][1]) % mod);
		}
	}

}

        


OK这个10870题同理

图片之后补上。先去睡觉~~~~~~

上代码~嘻嘻

 #include<cstdio>
#include<cstring>
const int MAXN=20;
long long d,n,mod;
long long  f[MAXN];
struct  Matrix
{
	long long a[MAXN][MAXN];
	void init()
	{
			memset(a,0,sizeof(a));
	}
	Matrix()
	{
		memset(a,0,sizeof(a));
	}
	Matrix  &operator *(const Matrix &b)
	{
		Matrix temp;  
		//memset(temp.a,0,sizeof(temp.a));
		  for(int i=0;i<d;i++)
       {
               for(int j=0;j<d;j++)
               {
                       for(int k=0;k<d;k++)
                       {
                               temp.a[i][j]=(temp.a[i][j]+a[i][k]*b.a[k][j] ) %mod;
                       }
               }
       }
		*this=temp;
		return *this;
	}


}a;

void myPow(long long n)        
{  
	Matrix b;

	//单位矩阵
	for(int i=0;i<d;i++)
		b.a[i][i]= 1;


	while(n>0)
	{
		if(1&n)
			b=b*a;

		a=a*a;
		n>>=1;
	}

	a=b;
}  

int main()
{
	while(scanf("%lld%lld%lld",&d,&n,&mod),d||n||mod)
	{
		a.init();
		for(int i=0;i<d;i++)
		{
				scanf("%lld",&a.a[0][i]);
				a.a[0][i]%=mod;
		}
		for(int i=0;i<d;i++)
			{
				scanf("%lld",&f[i]);
				f[i]%=mod;
		}

		
			for(int i=1;i<d;i++)
			{
				a.a[i][i-1]=1;
			}

			myPow(n-d);

			long long ans=0;
			for(int i=0;i<d;i++)
				ans=(ans+a.a[0][i]*f[d-i-1]) %mod;

			
			printf("%lld\n",ans);
		}

	return 0;

}

        



你可能感兴趣的:(UVA 10870 Recurrences 矩阵快速幂)