您的位置:首页 > 其它

uva 10743 - Blocks on Blocks(矩阵快速幂)

2014-08-02 10:33 190 查看
题目链接: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;
}


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: