您的位置:首页 > 其它

BZOJ 2326 HNOI 2011 数学作业 矩阵乘法求数列第n项

2015-12-02 19:28 537 查看


对于fn=12345678910...n,有fn=fn-1*(10^(floor(lgn)+1))+n。

所以构造矩阵:

10^(floor(lgn)+1) 0 0

1                 1 0

0                 1 1

实际上,对于1位数就是10^1,2位数就是10^2。每次矩阵乘够10^i-10^(i-1)即可,其中i表示位数,最后一次乘的次数不一样.

发现换了一种写法程序就麻烦了好多。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
#define FOR(i,j,k) for(i=j;i<=k;i++)
ll read() {
ll s = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while ('0' <= ch && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s;
}
ll n, p;
struct Matrix {
ll a[4][4];
Matrix(int flag) {
int i, j;
FOR(i,1,3) FOR(j,1,3) a[i][j] = flag & (i == j);
}
Matrix(bool, ll digit) {
a[1][1] = digit;
a[2][1] = a[2][2] = a[3][2] = a[3][3] = 1;
a[1][3] = a[1][2] = a[2][3] = a[3][1] = 0;
}
ll* operator [] (int x) { return a[x]; }
friend void operator *= (Matrix &x, Matrix y) {
int i, j, k;
Matrix z(0);
FOR(i,1,3) FOR(j,1,3) FOR(k,1,3)
z[i][j] = (z[i][j] + x[i][k] * y[k][j]) % p;
x = z;
}
friend Matrix operator ^(Matrix x, ll y) {
Matrix re(1);
for (; y; x *= x, y >>= 1) if(y & 1) re *= x;
return re;
}
} ans(1);
int main() {
ll i;
n = read(); p = read();
for (i = 10; i <= n; i *= 10)
ans *= Matrix(1, i % p) ^ (i - i / 10);
ans *= Matrix(1, i % p) ^ (n - i / 10 + 1);
printf("%llu", (ans[2][1] + ans[3][1]) % p);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: