hdu 2429矩阵乘法 2008 成都

题意:给出了n(n<=30)个串,首先给出一个初始的串,然后两个人轮着从n个串中选择一个串往后边放,要求当前串的第一个字符和上个串的最后一个字符是相同的,有一个成功的串,如果取到成功成功的串就算赢了。 两个人都是随机选串。现在问在m盘内第一个人赢得不同情况有多少种?

 

思路: 这道题是一道矩阵乘法的题,这一点开始的时候,后来糊涂,弄错了关系。 错了好几次才改过来。 首先根据串的关系,建立一个矩阵A。然后就是求出A+A^3+A^5...+ A^(m/2+m%2);这里推出了一个东西就是

 (S2n     A)       (A^2,  0)   =         (S2n+2     A)

  (S2*n-1 E)         (A,      E)                (S2*n+1    E)   

由这个关系可以利用矩阵的快速幂算出答案。 

开始的时候糊涂了, 算了一个 sum (A^i),以至于wa了好几次

AC代码:

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 65, P = 10001;

int map[N][N], n, s, t, m, nn;
char str[N][12], ss[12],st[12];
void mul(int a[][N], int b[][N]);

void init()
{
    int len;
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
    {
        scanf("%s", str[i]);
    }
    memset(map, 0, sizeof(map));

    for(int i=1; i<=n; i++)
    {
        len = strlen(str[i]);
        for(int j=1; j<=n; j++)
        {
            if(str[i][len-1] == str[j][0])
                map[i][j] = 1;
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            map[i+n][j] = map[i][j];
        }
        map[i+n][i+n] = 1;
    }
    mul(map, map);
    scanf("%s", ss);
    scanf("%s", st);
    for(int i=1; i<=n; i++)
    {
        if(strcmp(ss, str[i]) == 0)
            s = i;
        if(strcmp(st, str[i]) == 0)
            t = i;
    }
    nn = n;
    n *= 2;
    scanf("%d", &m);

}

void mul(int a[][N], int b[][N])
{
    int i,j,k;
    int c[N][N];
    for(i = 1; i <= n; i++)
        for(j = 1; j <= n; j++)
        {
            c[i][j] = 0;
            for(k = 1; k <= n; k++)
            {
                c[i][j] = c[i][j] + a[i][k]*b[k][j];
                c[i][j] = c[i][j] % P;
            }
        }
    for(i = 1; i <= n; i++)
        for(j = 1; j <= n; j++)
            a[i][j] = c[i][j];
}


void solve()
{
    int i,j,k;
    int ans;
    int arraya[N][N],arrayb[N][N];
    memset(arraya,0,sizeof(arraya));
    for(i = 1; i <= n; i++)
        arraya[i][i] = 1;
    for(i = 1; i <= n; i++)
        for(j = 1; j <= n; j++)
            arrayb[i][j] = map[i][j];
    m = (m+1)/2;
    while(m)
    {
        if(1&m)
            mul(arraya,arrayb);
        mul(arrayb,arrayb);
        m = m>>1;
    }
    memset(arrayb, 0, sizeof(arrayb));
    for(int i=1; i<=nn; i++)
    {
        for(int j=1; j<=nn; j++)
         {
             arrayb[i][j+nn] = map[i+nn][j];
         }
        arrayb[i+nn][i+nn] = 1;
    }
    mul(arrayb,arraya);
    printf("%d\n",arrayb[s+nn][t]);
}

int main()
{
    int t;
   // freopen("t.txt", "r", stdin);
    scanf("%d", &t);
    while(t--)
    {
        init();
        solve();
    }
    return 0;
}
posted @ 2012-09-20 10:46  Gu Feiyang  阅读(300)  评论(0)    收藏  举报