hdu 1005 矩阵快速幂模板题
2016-02-10 19:28
423 查看
题意:A number sequence is defined as follows:
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
Given A, B, and n, you are to calculate the value of f(n).
分析:通常这类题,会给出一个公式,但是由于数据很大,时间复杂度很高,所以可以借助快速幂将a*b%k的复杂度降到logb,所以矩阵幂乘的复杂度可以降到O(n^3*logn).
主要是需要求出有效运算的矩阵,也就是幂乘的矩阵的形式。
此题的化简过程:
f(n)=A*f(n-1)+B*f(n-2) (Mathtype中,按住Shift和Ctrl,再按空格键,即可添加空格)
用矩阵乘法递推求得
![](http://my.csdn.net/uploads/201206/29/1340977623_7357.jpg)
递推可得
![](http://my.csdn.net/uploads/201206/29/1340977814_9942.jpg)
,这样只需求
![](http://my.csdn.net/uploads/201206/29/1340978024_8891.jpg)
对于
![](http://my.csdn.net/uploads/201206/29/1340978110_1721.jpg)
,当n为偶数时,
![](http://my.csdn.net/uploads/201206/29/1340978165_7273.jpg)
n为奇数时,
![](http://my.csdn.net/uploads/201206/29/1340978241_6170.jpg)
(以上过程copy自点击打开链接)
有了幂乘的矩阵,就直接套模板求就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int mod=7;
const int N = 3;
struct Mat {
int mat
;
};
int n=2, m;
int A,B;
Mat operator * (Mat a, Mat b) {
Mat c;
memset(c.mat, 0, sizeof(c.mat));
int i, j, k;
for(k = 0; k < n; ++k) {
for(i = 0; i < n; ++i) {
for(j = 0; j < n; ++j) {
c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
c.mat[i][j]%=mod;
}
}
}
return c;
}
Mat operator ^ (Mat a, int k) {
Mat c;
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
c.mat[i][j] = (i == j);
for(; k; k >>= 1) {
if(k&1) c = c*a;
a = a*a;
}
return c;
}
int main()
{
int i;
int k;
while(~scanf("%d%d%d",&A,&B,&k)&&(A+B+k)){
if(k==1||k==2)
{
printf("1\n");
continue;
}
Mat a;
a.mat[0][0]=A%mod;a.mat[0][1]=B%mod;
a.mat[1][0]=1;a.mat[1][1]=0;
Mat c=a^(k-2);
printf("%d\n",(c.mat[0][0]*1+c.mat[0][1]*1)%mod);
}
return 0;
}
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
Given A, B, and n, you are to calculate the value of f(n).
分析:通常这类题,会给出一个公式,但是由于数据很大,时间复杂度很高,所以可以借助快速幂将a*b%k的复杂度降到logb,所以矩阵幂乘的复杂度可以降到O(n^3*logn).
主要是需要求出有效运算的矩阵,也就是幂乘的矩阵的形式。
此题的化简过程:
f(n)=A*f(n-1)+B*f(n-2) (Mathtype中,按住Shift和Ctrl,再按空格键,即可添加空格)
用矩阵乘法递推求得
![](http://my.csdn.net/uploads/201206/29/1340977623_7357.jpg)
递推可得
![](http://my.csdn.net/uploads/201206/29/1340977814_9942.jpg)
,这样只需求
![](http://my.csdn.net/uploads/201206/29/1340978024_8891.jpg)
对于
![](http://my.csdn.net/uploads/201206/29/1340978110_1721.jpg)
,当n为偶数时,
![](http://my.csdn.net/uploads/201206/29/1340978165_7273.jpg)
n为奇数时,
![](http://my.csdn.net/uploads/201206/29/1340978241_6170.jpg)
(以上过程copy自点击打开链接)
有了幂乘的矩阵,就直接套模板求就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int mod=7;
const int N = 3;
struct Mat {
int mat
;
};
int n=2, m;
int A,B;
Mat operator * (Mat a, Mat b) {
Mat c;
memset(c.mat, 0, sizeof(c.mat));
int i, j, k;
for(k = 0; k < n; ++k) {
for(i = 0; i < n; ++i) {
for(j = 0; j < n; ++j) {
c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
c.mat[i][j]%=mod;
}
}
}
return c;
}
Mat operator ^ (Mat a, int k) {
Mat c;
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
c.mat[i][j] = (i == j);
for(; k; k >>= 1) {
if(k&1) c = c*a;
a = a*a;
}
return c;
}
int main()
{
int i;
int k;
while(~scanf("%d%d%d",&A,&B,&k)&&(A+B+k)){
if(k==1||k==2)
{
printf("1\n");
continue;
}
Mat a;
a.mat[0][0]=A%mod;a.mat[0][1]=B%mod;
a.mat[1][0]=1;a.mat[1][1]=0;
Mat c=a^(k-2);
printf("%d\n",(c.mat[0][0]*1+c.mat[0][1]*1)%mod);
}
return 0;
}
相关文章推荐
- Atitit。Tree文件解析器的原理流程与设计实现 java c# php js
- 【Linux学习014】特殊权限
- spi裸板程序
- Codeforces Round #342 (Div. 2)-C. K-special Tables(模拟)
- 子元素滚动不影响父元素
- 子元素滚动不影响父元素
- The Java™ Tutorials — Concurrency :Thread Objects 线程对象
- 移动网络
- Linux - 命令
- 活着就为改变世界 -- 目录
- 杭电ACM1408——盐水的故事
- Atitit. 真正的全中国文字attilax易语言的特点以及范例
- 蓝桥杯 算法训练 ALGO-3 K好数
- 18 图形界面
- Atitit. 真正的全中国文字attilax易语言的特点以及范例
- Codeforces Round #342 (Div. 2)-B. War of the Corporations(模拟)
- Atitit. 真正的全中国文字attilax易语言的特点以及范例
- Android Volley完全解析(一),初识Volley的基本用法
- [Spring实战系列](14)Bean的自动检测
- 黑马程序员-学习笔记C语言01