标签:
题意:
给出一个数字N(1e18),求1 ~ N 的数字排起来mod上M(<= 1e9)的值。
题解:
0.定义f[x]表示以数字x结尾的数字mod 上 M 的值。
1.
f[x] = f[x-1] * 10 + x - 1 + 1 x为个位数的情况
f[x] = f[x-1] * 100 + x - 1 + 1 x为两位数的情况
f[x] = f[x-1] * 1000 + x - 1 + 1 x为三位数的情况
......
2.这样就可以对不同位数的数建立矩阵进行加速转移
/**************************************************************
Problem: 2326
User: xgtao
Language: C++
Result: Accepted
Time:24 ms
Memory:1288 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
ll mod, n, pow[25];
struct Matrix {
ll map[3][3];
void clear () { memset (map, 0, sizeof (map));}
};
Matrix MatrixMul (Matrix x, Matrix y) {
Matrix ret;
ret.clear();
for (int i = 0; i < 3; ++i)
for (int j = 0;j < 3; ++j)
for (int k = 0; k < 3; ++k)
ret.map[i][j] = (ret.map[i][j] + x.map[i][k] * y.map[k][j] % mod) % mod;
return ret;
}
Matrix MatrixPow (Matrix x, ll n) {
Matrix ret;
ret.clear();
ret.map[0][0] = ret.map[1][1] = ret.map[2][2] = 1;
while (n) {
if (n & 1) ret = MatrixMul(ret, x);
x = MatrixMul(x, x);
n >>= 1;
}
return ret;
}
Matrix calc (ll x, ll n) {
Matrix ret;
ret.clear();
ret.map[0][0] = x % mod;
ret.map[0][1] = 0;
ret.map[0][2] = 0;
ret.map[1][0] = 1;
ret.map[1][1] = 1;
ret.map[1][2] = 0;
ret.map[2][0] = 1;
ret.map[2][1] = 1;
ret.map[2][2] = 1;
return MatrixPow(ret, n);
}
int main () {
pow[0] = 1;
for (int i = 1; i <= 18; ++i) pow[i] = pow[i - 1] * 10;
cin >> n >> mod;
int cur = 1;
Matrix ans;
ans.clear();
ans.map[0][0] = ans.map[1][1] = ans.map[2][2] = 1;
while (true) {
ll L = pow[cur - 1], R = min (n, pow[cur] - 1);
ans = MatrixMul (ans, calc(pow[cur], R - L + 1));
++cur;
if (R == n) break;
}
cout << ans.map[2][0] << endl;
return 0;
}
标签:
原文地址:http://www.cnblogs.com/xgtao/p/5964527.html