题目链接:HDU 5318 The Goddess Of The Moon
题意:给出N串字符串,若是一个字符串的后缀与另一个字符串的前缀相同并且长度大于1,就表示这两个字符串是可以相连的,问M个字符串相连不同方案数为多少。
思路:
1.将输入的字符串预处理存入一个矩阵中,mp[i][j]=1说明str[i]与str[j]能相连,反之,则不能相连。
2.str[i]与str[j]能相连 转化为 i点到j点可达,那么就可以得到一个有向图,长度为M的意思就是 两点之间所走的步数为M的不同走法有多少种——矩阵快速幂的经典问题
注意:
1.因为求不同的方案数,所以输入是要先去重
AC代码:
#include <stdio.h>
#include <string.h>
#include <string>
#include <map>
#include <iostream>
#define LL __int64
using namespace std;
const int kmod=1000000007;
string str[55],ss;
map<string,int> mp;
int N;
struct Matrix {
LL m[55][55];
};
Matrix init;
Matrix MatrixMul(Matrix a, Matrix b){
Matrix c;
int i,j,k;
for(i=0;i<N;i++){
for(j=0;j<N;j++){
c.m[i][j]=0;
for(k=0;k<N;k++){
c.m[i][j]+=(a.m[i][k]*b.m[k][j]);
c.m[i][j]%=kmod;
}
}
}
return c;
}
Matrix QuickPow(Matrix m,int p){
Matrix b;
int i;
memset(b.m,0,sizeof b.m);
for(i=0;i<N;i++)
b.m[i][i]=1;
while(p){
if(p%2) b=MatrixMul(b,m);
p/=2;
m=MatrixMul(m,m);
}
return b;
}
int gao(string a, string b) {
int i,la,lb,j;
la=a.length();
lb=b.length();
string ta,tb;
for(i=0; i<la; i++) {
ta=a.substr(i);
//cout<<ta<<"---"<<endl;
for(j=0; j<=lb; j++) {
tb=b.substr(0,j);
//cout<<tb<<"..."<<endl;
if(ta==tb && (int)ta.length()>1) return 1;
}
}
return 0;
}
void solve(int n) {
int i,j;
memset(init.m,0,sizeof init.m);
for(i=0; i<n; i++) {
for(j=0; j<n; j++) {
if(i==j && (int)str[i].length()>1) init.m[i][j]=1;
else init.m[i][j]=gao(str[i],str[j]);
}
}
}
/*
*/
int main() {
//printf("%d\n",gao("1212","12"));
int i,k,n,m;
int t,cnt,j;
scanf("%d",&t);
while(t--) {
mp.clear();
cnt=0,k=0;
scanf("%d %d",&n,&m);
for(i=0; i<n; i++) {
cin>>ss;
if(mp.find(ss)==mp.end()) {
mp[ss]=k++;
str[cnt++]=ss;
}
}
N=cnt;
solve(n);
if(m==0) {
printf("0\n");
continue;
}
Matrix ans;
ans=QuickPow(init,m-1);
LL sum=0;
for(i=0;i<N;i++){
for(j=0;j<N;j++){
// printf("%I64d ",ans.m[i][j]);
sum+=ans.m[i][j];
sum%=kmod;
}
//printf("\n");
}
printf("%I64d\n",sum);
}
return 0;
}
/*
131
3 4
121 123 213
131
3 3
121 123 213
2
3 10
12 1213 1212
*/