hdu5318 The Goddess Of The Moon(dp+矩阵)

来源:互联网 发布:淘宝常用模块怎么设置 编辑:程序博客网 时间:2024/05/18 00:58

hdu5318

题目

http://acm.hdu.edu.cn/showproblem.php?pid=5318

思路

题意就是给n个串,串和串可以相连的条件就是一个串的后缀与另一个的前缀相同而且相同部分长度大于1,问有多少种方案连了m个串。
dp[i][j],当链接了i个串后,以第j个串结尾的有多少种。这样dp[i][j] = ∑dp[i-1][k] (k串后面可以接j)也就是dp[i][j] += dp[i-1][k]*a[k][j],a[k][j]是预处理好的k串和j串是否可接。可以用矩阵优化。
注意矩阵的初始化以及要排除一开始的重复的串,否则会导致多算。

代码

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<fstream>#include<set>using namespace std;#define ll long longconst int mod=1000000007;int n,m;char chain[60][20];int con[60][60];struct ma{    int a[60][60];};ma mul(ma a,ma b){    ma c;    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)        {            c.a[i][j]=0;//!            for(int k=0; k<n; k++)            {                c.a[i][j]=(c.a[i][j]+(ll)a.a[i][k]*b.a[k][j])%mod;            }        }    return c;}ma qmul(ma a,int temp){    ma c,ans;    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)        {            c.a[i][j]=a.a[i][j];            if(i==j)                ans.a[i][j]=1;            else                ans.a[i][j]=0;        }    while(temp>0)    {        if(temp&1)        {            ans=mul(ans,c);        }        c=mul(c,c);        temp/=2;    }    return ans;}int getcon(int x,int y){    int lx=strlen(chain[x]);    int ly=strlen(chain[y]);    if(lx==1||ly==1) return 0;    for(int i=lx-2; i>=0; i--)    {        int j=0;        int p=i;        while(chain[x][p]==chain[y][j]&&j<ly&&p<lx)        {            p++;            j++;        }        if(p==lx) return 1;    }    return 0;}int solve(){    ma p,c;    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)        {            if(getcon(i,j))                con[i][j]=1;            c.a[i][j]=con[i][j];        }    for(int i=0; i<n; i++)        for(int j=0; j<n; j++)        {            if(i==0) p.a[i][j]=1;            else p.a[i][j]=0;        }    c=qmul(c,m-1);    p=mul(p,c);    int ans=0;    for(int i=0; i<n; i++)    {        ans+=(p.a[0][i]%mod);        ans%=mod;    }    return ans;}set <string> st;int main(){    int T;    scanf("%d",&T);    while(T--)    {        memset(con,0,sizeof(con));        st.clear();        scanf("%d %d",&n,&m);        for(int i=0; i<n; i++)        {            scanf("%s",chain[i]);            st.insert(chain[i]);        }        int tn = 0;        set<string>::iterator it;        for(it=st.begin(); it!=st.end(); it++)            strcpy(chain[tn++],it->c_str());        n=tn;        printf("%d\n",solve());    }    return 0;}
0 0
原创粉丝点击