矩阵快速幂(以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 ...
随机推荐
- Java Web(十) 分页功能
分页 分页的使用非常普遍,现在一步步的把分页功能实现出来,先看看已经写好的效果: 该页面的所有数据都存放在一个javaBean对象(PageBean)里,每次访问该页面时,Serlvet就会把page ...
- Win10系列:JavaScript获取文件和文件夹列表
在应用程序中有时可能需要获取用户库中的内容,以便执行相关的操作.如果要获取某个用户库中的内容,需要先获取到这个用户库,获得用户库可以通过Windows.Storage命名空间中的KnownFolder ...
- js中 offset /client /scroll总结
offset家族(只能读取,不能操作): offsetLeft:元素的边框的外边缘距离与已定位的父容器(offsetparent)的左边距离(就是子元素左边框到父元素左边框的距离). offsetTo ...
- awk 中 fieldwidths使用方法
AWK中的FIELDWIDTHS是一个很好用的变量,这个变量可以指定字符串按照怎么样的宽度进行展示 实例一: 要求: 032130 032131 146230 035048 222049 095070 ...
- flask项目结构(二)创建flask,同步docker
简介: 建立flask容易,那么部署就比较麻烦了,配这个,配那个,更新………… 所以我从构建,就考虑部署的问题,使用docker部署. 程序都打包进docker,本博客有相关文章. pycharn直接 ...
- uitableView group模式下的间距问题
我么在使用group模式定义tableview的时候,系统默认是会有head和foot的间距的,来区分我们不同的group:在具体使用的时候又时候我们不需要这个间距.我们可以重新赋值这些间距来达到我们 ...
- ubuntu下修改MYSQL数据库密码
在介绍修改密码之前,先介绍一个文件/etc/MySQL/debian.cnf.其主要内容如下图: 里面有一个debian-sys-maint用户,这个用户只有Debian或Ubuntu服务器才有,所以 ...
- ORA-02049: 超时: 分布式事务处理等待锁
java.sql.SQLSyntaxErrorException: ORA-02049: 超时: 分布式事务处理等待锁 ORA-06512: 在 "HECDEV.BGT_JOURNAL_BA ...
- 7系列FPGA远程更新方案-QuickBoot(转)
reference: http://xilinx.eetrend.com/d6-xilinx/article/2014-04/7009.html reference : quickboot meth ...
- 51nod1009
给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数. 例如:n = 12,包含了5个1.1,10,12共包含3个1,11包含2个1,总共5个1. Input 输入N( ...