题目链接:uva 10743 - Blocks on Blocks
题目大意:问说n联骨牌有多少种,旋转镜像后相同不算同一组,一行的格子必须连续,如果答案大于10000,输出后四位。
解题思路:想了一下午的递推式,实在受不了,把推出的序列在网上搜了一下,有公式ai=5?ai?1?7?ai?2+4?ai?3
(i≥5)
PS:哪位神人知道怎么推出来的请留言我,大恩不言谢~
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 3;
const int mod = 10000;
int sign[maxn][maxn] = { {0, 1, 0}, {0, 0, 1}, {4, -7, 5} };
struct MAT {
int s[maxn][maxn];
MAT () {}
void set () {
for (int i = 0; i < maxn; i++)
for (int j = 0; j < maxn; j++)
s[i][j] = sign[i][j];
}
MAT operator * (const MAT& a) {
MAT ans;
for (int i = 0; i < maxn; i++) {
for (int j = 0; j < maxn; j++) {
ans.s[i][j] = 0;
for (int k = 0; k < maxn; k++)
ans.s[i][j] = (ans.s[i][j] + s[i][k] * a.s[k][j] % mod) % mod;
}
}
return ans;
}
};
MAT pow_mat (int n) {
MAT ans, x;
ans.set();
x.set();
while (n) {
if (n&1)
ans = ans * x;
x = x * x;
n >>= 1;
}
return ans;
}
int solve (int n) {
if (n < 3)
return n;
else if (n == 3)
return 6;
else if (n == 4)
return 19;
MAT ans = pow_mat(n-5);
return ((ans.s[2][0] * 2 + ans.s[2][1] * 6 + ans.s[2][2] * 19) % mod + mod) % mod;
}
int main () {
int cas, n;
scanf("%d", &cas);
for (int i = 1; i <= cas; i++) {
scanf("%d", &n);
printf("Case %d: ", i);
int ans = solve(n);
if (n <= 9)
printf("%d\n", ans);
else
printf("%04d\n", ans);
}
return 0;
}
uva 10743 - Blocks on Blocks(矩阵快速幂)
时间: 2024-10-28 19:37:09