矩阵快速幂(以HDU1757为例)
对于数据量大的求余运算,在有递推式的情况下,可以构造矩阵求解。
A - A Simple Math Problem
If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .
Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
InputThe problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
OutputFor each case, output f(k) % m in one line.Sample Input
10 9999
1 1 1 1 1 1 1 1 1 1
20 500
1 0 1 0 1 0 1 0 1 0
Sample Output
45
104 对于以上题目,已经给出递推式,可以获得如下矩阵:

因而只需要用矩阵快速幂求出第一行所得结果对题中所给数据求余的结果即是答案。
首先定义矩阵结构体,并且重载运算符*:
struct Matrix
{
long long mat[maxn][maxn];
Matrix operator*(const Matrix& m)const///重载*运算符,使其能进行矩阵相乘的运算
{
Matrix tmp;
for(int i = ; i < maxn ; i++)
{
for(int j = ; j < maxn ; j++)
{
tmp.mat[i][j] = ;
for(int k = ; k < maxn ; k++)
{
tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%mod;
tmp.mat[i][j] %= mod;
}
}
}
return tmp;
}
};
以下是矩阵快速幂函数:
long long Fast_Matrax(Matrix &m , int k)
{
Matrix ans;
memset(ans.mat , , sizeof(ans.mat));
for(int i = ; i < maxn ; i++)
ans.mat[i][i] = ;///对角线上的数应该都为1
k -= ;///递推公式中有9个子项
while(k)///进行矩阵的快速幂运算
{
if(k&)
ans = ans*m;
k >>= ;///相当于k/=2
m = m*m;
}
long long sum = ;
for(int i = ; i < maxn ; i++)///由于矩阵快速幂之后要与对应的子函数相乘然后进行相加求和,其中
{
sum += ans.mat[][i]*f[maxn-i-]%mod;
sum %= mod;///需要注意这里的一条定理,每个数除以x的余数之和等于它们的和的除以x的余数
}
return sum;
}
解本题的完整代码如下:
#include<cstdio>
#include<cstring>
using namespace std; const int maxn=;
long long k,mod;
int a[maxn],f[maxn]; struct Matrix
{
long long mat[maxn][maxn];
Matrix operator*(const Matrix& m)const///重载*运算符,使其能进行矩阵相乘的运算
{
Matrix tmp;
for(int i = ; i < maxn ; i++)
{
for(int j = ; j < maxn ; j++)
{
tmp.mat[i][j] = ;
for(int k = ; k < maxn ; k++)
{
tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%mod;
tmp.mat[i][j] %= mod;
}
}
}
return tmp;
}
}; void init(Matrix &m)
{
memset(m.mat , , sizeof(m.mat));
for(int i = ; i < maxn ; i++)
m.mat[][i] = a[i];
for(int i = ; i < maxn - ; i++)
m.mat[i+][i] = ;
for(int i = ; i < maxn ; i++)
f[i] = i;
} long long Fast_Matrax(Matrix &m , int k)
{
Matrix ans;
memset(ans.mat , , sizeof(ans.mat));
for(int i = ; i < maxn ; i++)
ans.mat[i][i] = ;///对角线上的数应该都为1
k -= ;///递推公式中有9个子项
while(k)///进行矩阵的快速幂运算
{
if(k&)
ans = ans*m;
k >>= ;///相当于k/=2
m = m*m;
}
long long sum = ;
for(int i = ; i < maxn ; i++)///由于矩阵快速幂之后要与对应的子函数相乘然后进行相加求和,其中
{
sum += ans.mat[][i]*f[maxn-i-]%mod;
sum %= mod;///需要注意这里的一条定理,每个数除以x的余数之和等于它们的和的除以x的余数
}
return sum;
} int main()
{
Matrix m;
while(~scanf("%lld%lld",&k,&mod))
{
for(int i=; i<; i++)
scanf("%d",&a[i]);
init(m);
if(k<)
printf("%d\n",k%mod);
else
printf("%lld\n",Fast_Matrax(m,k));
}
return ;
}
其中快速幂算法如下:
int PowerMod(int a, int b, int c)///a为底数,b为幂数,c为要除以的数,有时需要使用long long类型
{
int ans = ;
a = a % c;
while(b)
{
if(b&)///位运算,判断是否为奇数
ans = (ans * a) % c;
b >>=;///等价于b/=2
a = (a * a) % c;
}
return ans;
}
矩阵快速幂即是将上述算法中的正整数换成矩阵进行相乘,然后取矩阵第一行进行函数求和取余。需要注意的是在本题中重载预算符时已经对矩阵中的数进行了求余运算,因此保证了矩阵中的数在一定范围内,并且之后需要进行递推公式中的函数求和,在求和的过程中可以直接取余相加。
矩阵快速幂(以HDU1757为例)的更多相关文章
- 题解报告:poj 3233 Matrix Power Series(矩阵快速幂)
题目链接:http://poj.org/problem?id=3233 Description Given a n × n matrix A and a positive integer k, fin ...
- 矩阵快速幂(入门) 学习笔记hdu1005, hdu1575, hdu1757
矩阵快速幂是基于普通的快速幂的一种扩展,如果不知道的快速幂的请参见http://www.cnblogs.com/Howe-Young/p/4097277.html.二进制这个东西太神奇了,好多优秀的算 ...
- HDU1757 A Simple Math Problem 矩阵快速幂
A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- hdu2604(递推,矩阵快速幂)
题目链接:hdu2604 这题重要的递推公式,找到公式就很easy了(这道题和hdu1757(题解)类似,只是这道题需要自己推公式) 可以直接找规律,推出递推公式,也有另一种找递推公式的方法:(PS: ...
- 矩阵乘法&矩阵快速幂&矩阵快速幂解决线性递推式
矩阵乘法,顾名思义矩阵与矩阵相乘, 两矩阵可相乘的前提:第一个矩阵的行与第二个矩阵的列相等 相乘原则: a b * A B = a*A+b*C a*c+b*D c d ...
- nyoj_148_fibonacci数列(二)_矩阵快速幂
fibonacci数列(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 In the Fibonacci integer sequence, F0 = 0, F ...
- jiulianhuan 快速幂--矩阵快速幂
题目信息: 1471: Jiulianhuan 时间限制: 1 Sec 内存限制: 128 MB 提交: 95 解决: 22 题目描述 For each data set in the input ...
- fibonacci数列(二)_矩阵快速幂
描述 In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For exampl ...
- bnuoj 34985 Elegant String DP+矩阵快速幂
题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 We define a kind of strings as elegant s ...
随机推荐
- elasticsearch设置外部可访问
修改/config/elasticsearch.yml文件,增加如下配置: network.host: 0.0.0.0 浏览器访问http://192.168.17.134:9200/效果: 实际操作 ...
- assert用法
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义: void assert( int expression ); assert的作用 ...
- HTML代码转换为JavaScript字符串
我有时在工作中用到字符串拼接基本上来自于此,链接 http://www.css88.com/tool/html2js/
- python全栈开发笔记--------条件语句
Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. Python程序语言指定任何非0和非空(null)值为true,0 或者 null为false. Py ...
- jenkins+findbugs+checkstyle+PMD静态代码检查(二)
可以根据自己的需求选中对应的插件进行配置(不一定非要同时配置三个插件) jenkins:持续集成的工具 fundbugs:检测代码静态错误的插件 例如:定义了没有用到的对象,string类型的比较使 ...
- VSTO:使用C#开发Excel、Word【4】
<Visual Studio Tools for Office: Using C# with Excel, Word, Outlook, and InfoPath >——By Eric C ...
- MeshLab 编译
1.需要以下: MeshLab 1.3.3 下载地址 http://sourceforge.net/projects/meshlab/files/meshlab Win7 X64 Visual ...
- 201621123001 《Java程序设计》第8周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 Answer: 源 ...
- NioEventLoopGroup的构造函数
loop是对thread的封装,里面记录一个selector 一套打完,看下来,就是loopgroup里面一个loop的数组,每一个loop在 new的时候,传入了selector(第二个箭头), 第 ...
- javascript前进、后退、刷新的实现
go(-1): 返回上一页, 原页面表单中的内容会丢失; back(-1): 返回上一页, 原页表表单中的内容会保留. <input type=button value=刷新 onclick=& ...