HDU 1005 Number Sequence

题目链接:HDU 1005 Number Sequence

题目大意:
(f(1)=1,f(2)=1,f(n)=(A*f(n-1)+B*f(n-2))\%7)
给出(A)(B)(N)求出(f(N))

题解:
可以通过找规律的方法解决这道题,由于(f(n))要模(7),所以只有(0)~(6)七种情况,而(f(n))(f(n-1))的组合情况就只有(7 imes7=49)种,只要找到(f(n))(f(n-1))都是(1)的情况,就可以知道这个数列循环的周期。

为了训练矩阵快速幂,所以选择用矩阵快速幂来做这道题。

由递推公式构建矩阵:

[ left( egin{matrix} f(n-1) & f(n-2) end{matrix} ight) imes left( egin{matrix} a & 1 \ b & 0 end{matrix} ight)= left( egin{matrix} f(n) & f(n-1) end{matrix} ight) ]

通过矩阵快速幂和矩阵乘法得到(f(n))

#include <iostream>
#include <cstring>
using namespace std;
#define ms(a, b) memset(a, b, sizeof(a))
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define N 2

const int mod = 7;
int a, b, n;
struct Matrix {
	int num[N][N];
};

Matrix multi(Matrix a, Matrix b) {
	Matrix c;
	ms(c.num, 0);
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < N; ++j) {
			for (int k = 0; k < N; ++k) {
				c.num[i][j] += a.num[i][k] * b.num[k][j];
				c.num[i][j] %= mod;
			}
		}
	}
	return c;
}

Matrix fastPow(Matrix x, int k) {
	Matrix res;
	ms(res.num, 0);
	for (int i = 0; i < N; ++i) {
		res.num[i][i] = 1;
	}
	while (k) {
		if (k & 1) {
			res = multi(res, x);
		}
		x = multi(x, x);
		k >>= 1;
	}
	return res;
}

int main() {
	io_speed_up;
	while (cin >> a >> b >> n) {
		if (!a && !b && !n) {
			break;
		}
		Matrix temp;
		temp.num[0][0] = a;
		temp.num[0][1] = 1;
		temp.num[1][0] = b;
		temp.num[1][1] = 0;
		temp = fastPow(temp, n - 1);
		cout << (temp.num[0][1] + temp.num[1][1]) % mod << endl;
	}
	return 0;
}

P.S. 如果将矩阵快速幂代码写成如下,会不知为何而超时。

		temp = fastPow(temp, n - 2);
		cout << (temp.num[0][0] + temp.num[1][0]) % mod << endl;
原文地址:https://www.cnblogs.com/IzumiSagiri/p/13818369.html