P3216 题解:[HNOI2011] 数学作业
把拼接写成递推,位数相同的数放在一起,用矩阵快速幂整段处理。
把 到 依次拼接,数会长得很快。不过我们只需要余数,可以边拼边取模。
记拼到 时的结果为 。如果 有 位,就有
写成矩阵
递推里用到了拼接结果和当前的 ,再补一个常数 ,就能凑成行向量:
第一项得到 ,第二项从 变成 ,正好完成一次拼接。
按位数分段
一位数用同一个矩阵,两位数又用同一个矩阵。所以不用一个数一个数地算,可以让矩阵做快速幂,整段一起处理。
从 出发,依次处理这些分段。完整的一段 位数有 个,最后一段算到 为止。处理完后,第一维就是答案。
主要代码
// count 是 n 的十进制位数Matrix::Matrix<modint, 1, 3> unit = std::initializer_list<std::initializer_list<modint>>{{0, 0, 1}};u64 pow10 = 1;while (count --) { unit *= Matrix::Matrix3F<modint>{std::initializer_list<std::initializer_list<modint>>{{10 * pow10, 0, 0}, {1, 1, 0}, {1, 1, 1}}}.power(count ? 10 * pow10 - pow10 : n - pow10 + 1); pow10 *= 10;}std::cout << unit(0, 0) << "\n";