题目链接: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 */
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-10 08:54:15