对于数据量大的求余运算,在有递推式的情况下,可以构造矩阵求解。

A - A Simple Math Problem

Lele now is thinking about a simple function f(x).

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为例)的更多相关文章

  1. 题解报告:poj 3233 Matrix Power Series(矩阵快速幂)

    题目链接:http://poj.org/problem?id=3233 Description Given a n × n matrix A and a positive integer k, fin ...

  2. 矩阵快速幂(入门) 学习笔记hdu1005, hdu1575, hdu1757

    矩阵快速幂是基于普通的快速幂的一种扩展,如果不知道的快速幂的请参见http://www.cnblogs.com/Howe-Young/p/4097277.html.二进制这个东西太神奇了,好多优秀的算 ...

  3. HDU1757 A Simple Math Problem 矩阵快速幂

    A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  4. hdu2604(递推,矩阵快速幂)

    题目链接:hdu2604 这题重要的递推公式,找到公式就很easy了(这道题和hdu1757(题解)类似,只是这道题需要自己推公式) 可以直接找规律,推出递推公式,也有另一种找递推公式的方法:(PS: ...

  5. 矩阵乘法&矩阵快速幂&矩阵快速幂解决线性递推式

    矩阵乘法,顾名思义矩阵与矩阵相乘, 两矩阵可相乘的前提:第一个矩阵的行与第二个矩阵的列相等 相乘原则: a b     *     A B   =   a*A+b*C  a*c+b*D c d     ...

  6. nyoj_148_fibonacci数列(二)_矩阵快速幂

    fibonacci数列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 In the Fibonacci integer sequence, F0 = 0, F ...

  7. jiulianhuan 快速幂--矩阵快速幂

    题目信息: 1471: Jiulianhuan 时间限制: 1 Sec  内存限制: 128 MB 提交: 95  解决: 22 题目描述 For each data set in the input ...

  8. fibonacci数列(二)_矩阵快速幂

    描述 In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For exampl ...

  9. 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 ...

随机推荐

  1. JAVA常识1

    DBA:                     https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AE%A1%E7%90%86% ...

  2. ubuntu shell编程笔记

    and 命令 if  [   A  -a   B ] then else fi while [ ] do done set command set  these are parameters $1 s ...

  3. ubuntu下唤醒或休眠远程计算机

    ubuntu让我明白,没有什么完美的东西,要想完美必须付出代价.要么花时间折腾,要么花时间赚钱买系统. 人生也是一样,所以不要期待什么完美.哪有那么好的人,在合适的时间合适的地点让你遇见,还对你有感觉 ...

  4. linux下top命令参数详解

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器.下面详细介绍它的使用方法. 内存信息.内容如下: Mem: 191272k to ...

  5. 逆袭之旅DAY24.XIA.二重进阶、双色球

    一. 选择题. 1. 以下关于二重循环的说法正确的是(D). A. 二重循环就是一般程序中只能有两个循环 B. While循环不能嵌套在for循环里 C. 两个重叠的循环不能嵌套在第三个循环里. D. ...

  6. tomcat启动超时_tomcat was unable to start within

    参考: http://jingyan.baidu.com/article/64d05a025c9969de55f73b23.html 首先,你得确认下你的数据库连接,尤其是在多个服务器之间转换或者服务 ...

  7. 【原创】<Debug> “duplicate connection name”

    [Problem] duplicate connection name [Solution] 在Qt上使用SQLite的时候,如果第二次使用QSqlDatabase::addDatabase()方式时 ...

  8. js 设置img标签的src资源无法找到的替代图片(通过img的属性设置)

    在网站的前端页面设计中,要考虑到img图片资源的存在性,如果img的src图片资源不存在或显示不出来,则需要显示默认的图片.如何做到呢? 一.监听document的error事件 document.a ...

  9. 《Python》 计算机基础

    一.计算机基础: cpu:中央处理器,相当于人的大脑,运算中心,控制中心. 内存:暂时存储数据,与CPU交互. 优点:内存读取速度快. 缺点:容量小,造价高,断电即消失. 硬盘:长期存储数据. 优点: ...

  10. Android知识补充(Android学习笔记)

    Android知识补充 ●国际化 所谓的国际化,就是指软件在开发时就应该具备支持多种语言和地区的功能,也就是说开发的软件能同时应对不同国家和地区的用户访问,并针对不同国家和地区的用户,提供相应的.符合 ...