矩阵快速幂(以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 ...
随机推荐
- vs 编译库文件
vs编译的库文件 静态库 debug和release版本 需要分开编译,我编译和实践的结果. 但是我也发现有的debug release都用同一个(搞不清楚). 然后添加到工程应用. 静态库 附件 ...
- Win10系列:UWP界面布局基础9
在XAML中,样式.模板.画笔和动画等都被看做是资源,它们最终的作用都是相同的,就是让设计人员可以使用这些资源创建更好的视觉效果,对其设计的产品外观进行标准化统一,那么如何使用这些资源并组织和重用呢, ...
- day25 模块04_模块和包
休养生息--模块04 1.导入模块的执行的步骤 2.自定义模块 3.自定义包 一.导入模块的执行步骤 1).判断当前正在导入的模块是否已经导入过 2).如果已经导入过,不会重新导入该模块 3).如果没 ...
- 非图片格式如何转成lmdb格式--caffe
链接 LMDB is the database of choice when using Caffe with large datasets. This is a tutorial of how to ...
- linux 清空文件
将Linux文件清空的几种方法 1.使用重定向的方法 [root@centos7 ~]# du -h test.txt 4.0K test.txt [root@centos7 ~]# > tes ...
- android 自定义命名空间 http://schemas.android.com/apk/res-auto
XML中用 xmlns="http://schemas.android.com/apk/res-auto" 获取自定义属性值: public static String NAMES ...
- mybatis 异常 There is no getter for property named 'bizId' in 'class java.lang.Long'
mybatis 异常 There is no getter for property named 'bizId' in 'class java.lang.Long' 当使用mybatis进行传参的时候 ...
- mac下python2.7升级到3.6
1. 前言 Mac系统自带python2.7,本文目的是将自带的python升级到3.6版本. 网上有本多的做法是让python2.7和python3.X两个版本共存,博主并不知道,是两版本共存好,还 ...
- 大直播时代,P2P才是降低成本的必杀技
在流媒体传输分发领域,CDN和P2P一直是经常被拿来进行对比和讨论的一大热点,虽然不少大型视频企业目前同时使用着CDN和P2P两套分发机制,但相对于CDN,很多人对于P2P技术知之甚少.整体来说,P2 ...
- chrome 总崩溃的正确解决方法
解决办法: 原因就是 C:\Windows\System32\drivers\bd0001.sys 这个文件 可以把这个文件删除,或者重命名,删除或者重命名后一定要重启电脑,再打开Chrome就OK了 ...