您的位置:首页 > 其它

UVA 10870 Recurrences 矩阵快速幂

2013-09-24 23:25 477 查看
看题传送门: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

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





(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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: