分析:
題目有兩個條件:1.所選的字符串中任意兩個相鄰字符的ascll碼差值不超過32
2.至少存在一對相鄰的的字符ascll碼差值等於32.
看到這裏需要注意一點。題目說的是ascll碼差值不超過32就行,所以只要是32以內的都行。例如,字符b相鄰的可以是a~z還要加上B~Z,但是對於字符B來說,就只有A~Z加上a,b.
所一可以求出所有的滿足條件1的個數sum,但最終結果肯定比這個小,因爲sum裏面存在一些串,其中所有相鄰的字符ascll差值都小於32,所以要減去着一些串。
即:
我們設
那麼
…
…
Fz(n)=FZ(n−1)+Fa(n−1)+Fb(n−1)+Fc(n−1)+...+Fz(n−1)
我們設
那麼
…
…
建立變換矩陣,而後高速冪。
需要注意的是對於F和G的結尾個數不同,自己需要揣測清楚。例如F(Z)與G(Z)是不一樣的。
下面配一張圖是我寫的矩陣:
這張圖的左邊部分,即f(n-1)(A)......就是所有當字符長度爲3時的以A(或其他)結尾的串的個數,左右相乘箭頭右邊就是當字符長度爲4時的所有串的
個數。對於G(n)同理求得。
下面是代碼,如果還不理解,可以試試我的代碼,用裏面的print()函數,輸出初始化後的N1與N2分析。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 52
#define me(x) memset(x,0,sizeof(x))
#define ll long long
#define mod 1000000007
struct mat//用結構體封裝矩陣
{
ll m[maxn][maxn];
}unit,G,F,N1,N2;
void init()//初始化
{
me(unit.m);
me(G.m);
me(F.m);
me(N1.m);me(N2.m);
for(int i=0;i<26;i++)//單行
{
F.m[i][0]=27+i;
G.m[i][0]=F.m[i][0]-1;
unit.m[i][i]=1;
}
for(int i=26,j=0;i<52;i++,j+=2)//單行
{
F.m[i][0]=26+(i-j);
G.m[i][0]=F.m[i][0]-1;
unit.m[i][i]=1;
}
for(int i=0;i<52;i++)
{
unit.m[i][i]=1;
}
for(int i=0;i<26;i++)
{
for(int j=0;j<=i+26;j++)
{
N1.m[i][j]=1;
}
}
for(int i=26;i<52;i++)
{
for(int j=51;j>=i-26;j--)
{
N1.m[i][j]=1;
}
}
for(int i=0;i<26;i++)
{
for(int j=0;j<=i+25;j++)
{
N2.m[i][j]=1;
}
}
for(int i=26;i<52;i++)
{
for(int j=51;j>i-26;j--)
{
N2.m[i][j]=1;
}
}
}
void print(mat a)//自己寫的打印函數
{
int i,j;
for(i=0;i<maxn;i++)
{
for(j=0;j<maxn;j++)
printf("%d ",a.m[i][j]);
puts("");
}
puts("");
return ;
}
mat operator*(mat a,mat b)//對*運算符重載爲矩陣相乘
{
mat p;
for(int i=0;i<maxn;i++)
{
for(int j=0;j<maxn;j++)
{
p.m[i][j]=0;
for(int w=0;w<maxn;w++)
{
p.m[i][j]+=a.m[i][w]*b.m[w][j]%mod;
p.m[i][j]%=mod;
}
}
}
return p;
}
ll pow(mat N,int k,mat p)//矩陣快速冪
{
mat ans;
ll sum=0;
ans=unit;
while(k)
{
if(k&1)
{
ans=ans*N;
}
N=N*N;
k=k>>1;
}
ans=ans*p;
for(int i = 0 ; i < maxn ; i++)
{
for(int j=0;j <maxn;j++)
{
sum += ans.m[i][j];
// cout<<sum<<endl;
}
sum %= mod;
}
return sum%mod;//因爲ans[0][0]就是f(n);
}
int main()
{
init();
/*/cout<<3<<endl;
print(N1);
cout<<4<<endl;
print(N2);
cout<<5<<endl;
print(unit);*/
int n,t;
scanf("%d",&t);
long long cnt;
while(t--)
{
init();
scanf("%d",&n);
if(n==2) cout<<52<<endl;
else
{
//cout<<pow(N1,n-1,F)<<" "<<pow(N2,n-1,G)<<endl;
cnt=((pow(N1,n-2,F)-pow(N2,n-2,G))+mod)%mod;
cout<<cnt%mod<<endl;
}
}
return 0;
}