一开始以为递推公式是f[n]=2*f[n-1]+2*f[n-2]。但这个公式显然是错的,这个公式相当于限制了A,C必须成对出现,比如ABA这种就计算不到了。
到网上搜了一下才发现原来公式是这样的,设f1[n]为长度为n的序列,A,C都出现偶数次的方法数;f2[n]为长度为n的序列,A出现奇数次,C出现偶数次的方法数;f3[n]为长度为n的序列,A出现偶数次,C出现奇数次的方法数;f4[n]为长度为n的序列,A,C都出现奇数次的方法数。
f1[n] = 2*f1[n-1] + f2[n-1] + f3[n-1];
f2[n] = f1[n-1] + 2*f2[n-1] + f4[n-1];
f3[n] = f1[n-1] + 2*f3[n-1] + f4[n-1];
f4[n] = f2[n-1] + f3[n-1] + 2*f4[n-1];
使用矩阵递推即可。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <iostream>
#include <sstream>
#define ll __int64
using namespace std;
const int mat1_[4][4] = {
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1}
};
const int mat2_[4][4] = {
{2, 1, 1, 0},
{1, 2, 0, 1},
{1, 0, 2, 1},
{0, 1, 1, 2}
};
int mat1[4][4], mat2[4][4], mat3[4][4];
void mul(int mat1[4][4], int mat2[4][4]) {
int i, j, k;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
mat3[i][j] = 0;
for (k = 0; k < 4; k++)
mat3[i][j] += mat1[i][k] * mat2[k][j];
mat3[i][j] %= 100;
}
}
memcpy(mat1, mat3, sizeof(mat3));
}
int main() {
int t, c;
ll n;
while (scanf("%d", &t), t) {
for (c = 1; c <= t; c++) {
scanf("%I64d", &n);
printf("Case %d: ", c);
memcpy(mat1, mat1_, sizeof(mat1));
memcpy(mat2, mat2_, sizeof(mat2));
while (n) {
if (n & 1) mul(mat1, mat2);
mul(mat2, mat2);
n >>= 1;
}
printf("%d\n", mat1[0][0]);
}
printf("\n");
}
}