首页 > 其他 > 详细

BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )

时间:2015-11-26 21:16:12      阅读:338      评论:0      收藏:0      [点我收藏+]

技术分享

BZOJ先剧透了是矩阵乘法...这道题显然可以f(x) = f(x-1)*10t+x ,其中t表示x有多少位。

技术分享

 这个递推式可以变成这样的矩阵...(不会用公式编辑器...), 我们把位数相同的一起处理, 那么10^t就可以确定,加上快速幂就行了

------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
typedef int matrix[3][3];
 
ll N;
int MOD;
matrix mat, Q, tmp;
 
void Mul(matrix &a, matrix &b) {
memset(tmp, 0, sizeof tmp);
for(int i = 0; i < 3; i++)
for(int k = 0; k < 3; k++)
for(int j = 0; j < 3; j++)
if((tmp[i][j] += ll(a[i][k]) * b[k][j] % MOD) >= MOD)
tmp[i][j] -= MOD;
memcpy(a, tmp, sizeof a);
}
 
void Power(matrix &a, matrix &b, ll k) {
for(; k; k >>= 1, Mul(b, b))
if(k & 1) Mul(a, b);
}
 
void Init_matrix() {
memset(mat, 0, sizeof mat);
mat[0][1] = mat[0][2] = mat[1][1] = mat[1][2] = mat[2][2] = 1;
memset(Q, 0, sizeof Q);
for(int i = 0; i < 3; i++)
Q[i][i] = 1;
}
 
int main() {
scanf("%lld%d", &N, &MOD);
int len = 0, B = 0, C = 0;
ll p = 1;
for(ll t = N; t; t /= 10, len++);
for(int i = 1; i < len; i++) {
Init_matrix();
mat[0][0] = (p = p * 10) % MOD;
Power(Q, mat, p - p / 10);
B = (ll(B) * Q[0][0] % MOD + ll(C) * Q[0][1] % MOD + Q[0][2]) % MOD;
C = ((p % MOD) - 1 + MOD) % MOD;
}
Init_matrix();
mat[0][0] = p * 10 % MOD;
Power(Q, mat, N - p + 1);
B = (ll(B) * Q[0][0] % MOD + ll(C) * Q[0][1] % MOD + Q[0][2]) % MOD;
printf("%d\n", B);
return 0;
}

------------------------------------------------------------------------------------

2326: [HNOI2011]数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1452  Solved: 841
[Submit][Status][Discuss]

Description

技术分享

Input

Output

Sample Input

Sample Output

HINT

Source

 

BZOJ 2326: [HNOI2011]数学作业( 矩阵快速幂 )

原文:http://www.cnblogs.com/JSZX11556/p/4998660.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!