XTU 1440 Lonely prime number(Fibonacci)
时间:2010-03-17 来源:chhaya
求(Fib[a]p+ Fib[a+1]p+ Fib[a+2]p……….. + Fib[b]p ) mod p
[a,b]是个区间,p是个素数。 通过此题,算是把矩阵二分乘法快速求幂学会了,以后不会再想到矩阵就怕了。
还有两个公式: (x+y)^p mod p = (x^p+y^p) mod p
Fib[n+2]-1 = Fib[1]+Fib[2]+...Fib[n] (前n项Fib和)
(Fib[a]p+ Fib[a+1]p+ Fib[a+2]p……….. + Fib[b]p ) mod p
= (Fib[a]+ Fib[a+1]+ Fib[a+2]……….. + Fib[b])^p mod p
= ((Fib[b+2]-1) - (Fib[a+1]-1) ) ^ p mod p
而Fibonacci 数列跟矩阵的关系:
| Fib(n+1) Fib(n) | |1 1 |
| | = | | ^n
| Fib(n) Fib(n-1)| |1 0 |
为了快速求幂,用到了二分乘法: 来自http://blog.sina.com.cn/s/blog_51cea4040100g8e8.html
先摆代码:
long long qpow(int a, int b)
{
long long c, d;
c = 1; //存a^b
d = a; //存a的倍幂
while (b > 0)
{
if (b & 1) //或 if (b % 2 == 1)
c *= d;
b = b >> 1; //或 b = b / 2
d = d * d;
}
return c;
}
这里,我们举个列子,比如,a^22
(22)10进制 == (10110)2进制
(a^22)
(a^16)*(a^6)
(a^4)*(a^2)
(a^2)*1
(10110)%2=0 c=1,d=a^2;
(1011)%2=1 c=(a^2)*1,d=a^4;
(101)%2=1 c=(a^4)*(a^2)*1,d=a^8;
(10)%2=1 c=(a^4)*(a^2)*1,d=a^16;
(1)%2=1 c=(a^16)*(a^4)*(a^2)*1;
这样子矩阵求幂跟后面和求幂都可以用到二分,终于算是明白了。。
#include <stdio.h>
/*二分求矩阵幂,次函数求出的是Fib(a)*/
/* c[2][2] = r[2][2] * c[2][2] % p */
/*r[2][2] = r[2][2] * r[2][2] % p*/ |