[BZOJ 2326] [HNOI2011] 数学作业 【矩阵乘法】
题目链接:BZOJ - 2326
题目分析
数据范围达到了 10^18 ,显然需要矩阵乘法了!
可以发现,向数字尾部添加一个数字 x 的过程就是 Num = Num * 10^k + x 。其中 k 是 x 的位数。
那么位数相同的数字用矩阵乘法处理就可以了。
[Num, x, 1] * [10^k, 0, 0] = [Num*10^k+x, x+1, 1]
[ 1, 0, 0]
[ 0, 1, 1]
枚举位数,做多次矩阵乘法。
其中两个整数相乘可能会爆 LL ,那么就用类似快速幂的慢速乘。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; typedef long long LL; LL n, Mod; struct Matrix
{
int x, y;
LL A[5][5];
void Clear() {
memset(A, 0, sizeof(A));
}
void SetXY(int a, int b) {
x = a; y = b;
}
} M0, M_Ans, M_t; LL MulNum(LL a, LL b) {
LL f = a, ret = 0;
while (b) {
if (b & 1) {
ret += f;
if (ret > Mod) ret %= Mod;
}
b >>= 1;
f <<= 1;
if (f > Mod) f %= Mod;
}
return ret;
} Matrix Mul(Matrix Ma, Matrix Mb) {
Matrix ret;
ret.SetXY(Ma.x, Mb.y);
ret.Clear();
for (int i = 1; i <= ret.x; ++i) {
for (int j = 1; j <= ret.y; ++j) {
for (int k = 1; k <= Ma.y; ++k) {
ret.A[i][j] += MulNum(Ma.A[i][k], Mb.A[k][j]);
ret.A[i][j] %= Mod;
}
}
}
return ret;
} Matrix Pow(Matrix Ma, LL b) {
Matrix f, ret;
f = Ma;
ret.SetXY(Ma.x, Ma.y);
ret.Clear();
for (int i = 1; i <= ret.x; ++i) ret.A[i][i] = 1;
while (b) {
if (b & 1) ret = Mul(ret, f);
b >>= 1;
f = Mul(f, f);
}
return ret;
} int main()
{
scanf("%lld%lld", &n, &Mod);
LL Temp, Ans;
M0.SetXY(1, 3);
M0.Clear();
M0.A[1][1] = 0; M0.A[1][2] = 1; M0.A[1][3] = 1;
M_t.SetXY(3, 3);
Temp = 1;
for (int i = 1; i <= 18; ++i) {
Temp *= 10ll;
if (Temp > n) break;
M_t.Clear();
M_t.A[1][1] = Temp;
M_t.A[2][1] = M_t.A[2][2] = M_t.A[3][2] = M_t.A[3][3] = 1;
M_t = Pow(M_t, Temp - Temp / 10);
M0 = Mul(M0, M_t);
}
M_t.Clear();
M_t.A[1][1] = Temp;
M_t.A[2][1] = M_t.A[2][2] = M_t.A[3][2] = M_t.A[3][3] = 1;
M_t = Pow(M_t, n - Temp / 10 + 1);
M0 = Mul(M0, M_t);
Ans = M0.A[1][1];
printf("%lld\n", Ans);
return 0;
}
[BZOJ 2326] [HNOI2011] 数学作业 【矩阵乘法】的更多相关文章
- BZOJ 2326: [HNOI2011]数学作业(矩阵乘法)
传送门 解题思路 NOIp前看到的一道题,当时想了很久没想出来,NOIp后拿出来看竟然想出来了.注意到有递推\(f[i]=f[i-1]*poww[i]+i\),\(f[i]\)表示\(1-i\)连接起 ...
- BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )
BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位. 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理 ...
- bzoj 2326: [HNOI2011]数学作业【dp+矩阵快速幂】
矩阵乘法一般不满足交换律!!所以快速幂里需要注意乘的顺序!! 其实不难,设f[i]为i的答案,那么f[i]=(f[i-1]w[i]+i)%mod,w[i]是1e(i的位数),这个很容易写成矩阵的形式, ...
- bzoj 2326: [HNOI2011]数学作业
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #defin ...
- [BZOJ2326] [HNOI2011] 数学作业 (矩阵乘法)
Description Input Output Sample Input Sample Output HINT Source Solution 递推式长这样:$f[n]=f[n-1]*10^k+n$ ...
- 【bzoj2326】[HNOI2011]数学作业 矩阵乘法
题目描述 题解 矩阵乘法 考虑把相同位数的数放到一起处理: 设有$k$位的数为$[l,r]$,那么枚举从大到小的第$i$个数(即枚举$r-i+1$),考虑其对$Concatenate(l..r)$的贡 ...
- BZOJ-2326 数学作业 矩阵乘法快速幂+快速乘
2326: [HNOI2011]数学作业 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1564 Solved: 910 [Submit][Statu ...
- [HNOI2011]数学作业 --- 矩阵优化
[HNOI2011]数学作业 题目描述: 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M ,要求计算\(Concatenate(1..N)\; Mod\; ...
- 【BZOJ2326】【HNOI2011】数学作业 [矩阵乘法][DP]
数学作业 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Input 输入文件只有一行为用空 ...
随机推荐
- android 04 AbsoluteLayout
绝对布局:layout_x,layout_y:坐标精准定位 xml文件:不推荐使用 <AbsoluteLayout xmlns:android="http://schemas.andr ...
- linux 最大文件描述符fd
使用四种框架分别实现百万websocket常连接的服务器 著名的 C10K 问题提出的时候, 正是 2001 年.这篇文章可以说是高性能服务器开发的一个标志性文档,它讨论的就是单机为1万个连接提供服务 ...
- hadoop资料汇总(网上)
http://blog.csdn.net/fansy1990/article/list/3 全部是hadoop的,挺好. http://stackoverflow.com/ ...
- [转] React同构思想
React比较吸引我的地方在于其客户端-服务端同构特性,服务端-客户端可复用组件,本文来简单介绍下这一架构思想. 出于篇幅原因,本文不会介绍React基础,所以,如果你还不清楚React的state/ ...
- dev checkedlistbox动态绑定数据
最近在做项目的时候遇到个问题.用checkedlistbox控件绑定数据.在这里稍微总结一下. 其实动态绑定数据有两种方法下面说一下 1.通过数据源 DataTable dt=new DataTabl ...
- ng-view和ng-include之间的区别
ng-view通过使用路由控制,可以方便的实现页面组合,但一个html文件中,只能有一个ng-view,他是可以被ctl控制的.ng-include就是将多个页面的公共页面提取出来,如header.h ...
- iOS RC4加解密算法
-(NSString *)encrypt:(NSString *)string withKey:(NSString *)key{ self.sBox = [[self frameSBox:key] m ...
- 层模型--相对定位(position:relative)
如果想为元素设置层模型中的相对定位,需要设置position:relative(表示相对定位),它通过left.right.top.bottom属性确定元素在正常文档流中的偏移位置.相对定位完成的过程 ...
- C语言求2的100次方怎么解,大整数运算
#include "stdio.h"int ai[100]; void main(){ int a,b; ai[99]=1; for(b=0;b<100;b++) for( ...
- Visual Studio2010 安装msdn
1.注册VS2010 断网(不要冒险)->运行Microsoft Visual Studio 2010->帮助->注册产品->YCFHQ-9DWCY-DKV88-T2TMH-G ...