HDU 6172
这道题目一看就想到矩阵快速幂。可以先把 hn 算出来,进而把 bn , an 都算出来。但是发现一个问题,题目中是要求 ⌊an−−√⌋ 对 1e9+7 取模之后的值。但是开根号没法取模啊,所以就要换个思路了。
把 ⌊an−−√⌋ 的表打出来如下。
元素 | 值 |
---|---|
⌊a2−−√⌋ | 31 |
⌊a3−−√⌋ | 197 |
⌊a4−−√⌋ | 1255 |
⌊a5−−√⌋ | 7997 |
⌊a6−−√⌋ | 50959 |
⌊a7−−√⌋ | 324725 |
⌊a8−−√⌋ | 2069239 |
⌊a9−−√⌋ | 13185773 |
这样看去确实没有什么规律,但是转念一想,出题人一定会给我们一线生机的(队友的神想法)。题目中总共给了三个递推式,分别是 hn , bn , an 的递推式,其中 bn 的递推式一看就是扯犊子,麻烦的让人头晕。所以我们尝试着验证一下 ⌊an−−√⌋ 是否符合 hn 的递推式,不试不知道,一试吓一跳。原来 ⌊an−−√⌋ 的递推式和 hn 的神相似。就是 ⌊an−−√⌋=4⌊an−1−−−−√⌋+17⌊an−2−−−−√⌋−12⌊an−3−−−−√⌋ 。
所以用矩阵快速幂求出 ⌊an−−√⌋ 就行啦。
#include
#include
#include
using namespace std;
typedef long long int LL;
typedef vector vec;
typedef vector mat;
const int MOD = 1e9 + 7;
mat mul(mat A, mat B)
{
mat C(A.size(), vec(B[0].size()));
for (unsigned i = 0; i < A.size(); i++)
for (unsigned j = 0; j < B[0].size(); j++)
for (unsigned k = 0; k < B.size(); k++)
C[i][j] = (C[i][j] + A[i][k] * B[k][j] + MOD) % MOD; // 中间会出现负数,所以要先+MOD。
return C;
}
mat pow(mat A, LL n)
{
mat B(A.size(), vec(A.size()));
for (unsigned i = 0; i < A.size(); i++)
B[i][i] = 1;
while (n > 0)
{
if (n & 1) B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
int main()
{
//freopen("test.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T;
scanf("%d", &T);
while (T--)
{
LL n;
scanf("%I64d", &n);
if (n == 2)
{
printf("31\n");
continue;
}
else if (n == 3)
{
printf("197\n");
continue;
}
else if (n == 4)
{
printf("1255\n");
continue;
}
mat M1(3, vec(3));
M1[0][0] = 4;M1[0][1] = 17;M1[0][2] = -12;
M1[1][0] = 1;M1[1][1] = 0;M1[1][2] = 0;
M1[2][0] = 0;M1[2][1] = 1;M1[2][2] = 0;
mat M2(3, vec(1));
M2[0][0] = 1255;
M2[1][0] = 197;
M2[2][0] = 31;
mat ans = mul(pow(M1, n - 4), M2);
printf("%I64d\n", ans[0][0]);
}
return 0;
}