給定序列長度 n,序列由大小寫字母(A-Z, a-z,共 52 個字元)組成。相鄰字母的 ASCII 碼差值必須 ≤ 32,且序列中至少要有一組相鄰字母差值恰好等於 32。求合法序列總數模 1,000,000,007。
將 52 個字母編碼 0~25 對應 A-Z,26~51 對應 a-z。
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
const int SZ = 52;
const int64 MOD = 1'000'000'007LL;
struct Matrix {
int64 a[SZ][SZ];
Matrix(bool ident = false) { memset(a, 0, sizeof(a)); if (ident) for (int i=0;i>= 1;
}
return res;
}
Matrix buildBase(bool allowDiff32) {
Matrix M;
// 大寫字母 0-25
for (int i=0;i<26;++i) {
for (int j=0;j<=i+26;++j) M.a[j][i] = 1; // 修正:原碼邏輯為列為起點,行為終點,此處按原意填充
}
// 小寫字母 26-51
for (int i=26;i<52;++i) {
for (int j=51;j>=i-26;--j) M.a[j][i] = 1;
}
// 移除差值恰好為 32 的轉移 (大小寫同字母互轉)
if (!allowDiff32) {
for (int i=0;i<26;++i) {
M.a[i+26][i] = 0; // 大寫 -> 對應小寫
M.a[i][i+26] = 0; // 小寫 -> 對應大寫
}
}
return M;
}
int64 solve(long long n, bool allowDiff32) {
if (n == 1) return 52; // 長度1無相鄰限制
Matrix base = buildBase(allowDiff32);
Matrix res = mpow(base, n - 1);
int64 ans = 0;
for (int i=0;i> T;
while (T--) {
long long n; cin >> n;
int64 total = solve(n, true);
int64 no32 = solve(n, false);
cout << (total - no32 + MOD) % MOD << '\n';
}
return 0;
}
res = mul(res, ori) 代表向量乘在左側,需確保矩陣定義一致(行為 From,列為 To,或相反)。res.g[0][i] = 1 視為長度 1 時以各字母結尾的方案數為 1,故最終求首行和。long long 夠用(52 × MOD² < 2⁶³),但建議乘法後立即取模。