矩阵快速幂(以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 ...
随机推荐
- C#中使用SqlBulkCopy的批量插入和OracleBulkCopy的批量插入
1.首先我们做一下准备工作,在sql server和oracle分别建立一个Student表 oracle中 --创建Student表 -- create table Student( stuId n ...
- 【Jmeter基础知识】Jmeter的三种参数化方式
JMeter的三种参数化方式包括: 1.用户参数 2.函数助手 3.CSV Data Set Config 一.用户参数 位置:添加-前置处理器-用户参数 操作:可添加多个变量或者参数 二.函数助手 ...
- 【oracle】一些的常用命令
命令行连接oracle sqlplus 回车 分别输入用户名和密码 命令行重启oracle数据库 sqlplus /nolog conn 账号/密码 as sysdba shutdow immedi ...
- am335x system upgrade uboot nand boot(三)
在uboot 下初始化nand,一般需要做如下工作: 第一: 配置默认从NAND boot Index: include/configs/am335x_evm.h=================== ...
- fzu1977
题解: 和前两题差不多 只不过变成了有些一定走,有些不一定 代码: #include<cstdio> #include<cmath> #include<algorithm ...
- swiftlint 你所要知道的所有!!
swiftin Should the opening brace of a function or control flow statement be on a new line or not ?:) ...
- core net 实现post 跟get
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using Syst ...
- 【Appium】Appium工作原理
参考:http://www.cnblogs.com/zhjsll/p/5698878.html 原作者写的很好,所以直接放在这里. 一.什么是Appium Appium是一个开源.跨平台的测试框架,可 ...
- SpringBoot集成Swagger2实现Restful(类型转换错误解决办法)
1.pom.xml增加依赖包 <dependency> <groupId>io.springfox</groupId> <artifactId>spri ...
- 性能测试-11.Linux服务器使用NMON监控指标
一.NMON使用 首先下载nmon软件http://nmon.sourceforge.net/pmwiki.php?n=Site.Download,打开这个网站下载符合自己操作系统的硬件的相关nmon ...