bzoj1898 [Zjoi2005]Swamp 沼泽鳄鱼——矩阵快速幂

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1898

求到达方案数...还是矩阵快速幂;

能够到达就把邻接矩阵那里赋成1,有鳄鱼的地方从各处来的路径都是0;

因为时间周期只有2,3,4,所以每12个时间就是一个循环;

可以用矩阵快速幂做了。

一开始写了个一团糟,也不明白样例为什么输出0了...

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const mod=10000;
int n,m,st,ed,K,head[55],ct,nf,ey[25][5],te[25],ans[55],tmp[55];
struct E{
    int to,next; 
    E(int t=0,int n=0):to(t),next(n) {}
}edge[2505];
struct Matrix{
    int a[55][55];
    Matrix operator * (const Matrix &y) const
    {
        Matrix x;
        memset(x.a,0,sizeof x.a);
        for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
                for(int j=1;j<=n;j++)
                    (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod;
        return x;
    }
}s[15],b;
void add(int x,int y){edge[++ct]=E(y,head[x]); head[x]=ct;}
void build1()
{
    for(int x=1;x<=n;x++)
        for(int i=1;i<=12;i++)
            for(int j=head[x],u;j;j=edge[j].next)
                s[i].a[x][u=edge[j].to]=1;//
}
void build2()
{
    for(int i=1;i<=nf;i++)
        for(int t=1;t<=12;t++)
            for(int j=1;j<=n;j++)
            {
                int x=ey[i][t%te[i]];
    //            for(int k=head[x],y;k;k=edge[k].next)
    //                s[j].a[y=edge[k].to][x]=0;
                s[t].a[j][x]=0;
            }
}
//void init(Matrix &x)
//{
//    memset(x.a,0,sizeof x.a);
//    for(int i=1;i<=55;i++)
//        for(int j=55;j;j--)
//            x.a[i][j]=1;
//}
void mul2(int a[55],int b[55][55],int c[55])
{
    int tmp[55];
        for(int j=0;j<n;j++)
        {
            tmp[j]=0;
            for(int k=0;k<n;k++)
               tmp[j]=(tmp[j]+a[k]*b[k][j])%mod;
        }
        for(int j=0;j<n;j++)
            c[j]=tmp[j];
}
int main()
{
    scanf("%d%d%d%d%d",&n,&m,&st,&ed,&K);
    st++; ed++;
    for(int i=1,x,y;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        x++; y++;
        add(x,y); add(y,x);
    }
    scanf("%d",&nf);
    for(int i=1;i<=nf;i++)
    {
        scanf("%d",&te[i]);
        for(int j=1;j<=te[i];j++)
            scanf("%d",&ey[i][j]),ey[i][j]++;
    }
    build1(); build2();
//    init(s[13]);
    for(int i=1;i<=n;i++)
        b.a[i][i]=s[13].a[i][i]=1;
    for(int i=1;i<=12;i++)s[13]=s[13]*s[i];
//    Matrix b; init(b);
    int t=K/12;
    while(t)
    {
        if(t&1)b=b*s[13];
        s[13]=s[13]*s[13];
        t>>=1;
    }
    t=K%12;
    for(int i=1;i<=t;i++)b=b*s[i];
//    for(int i=1;i<=55;i++)
//        for(int j=1;j<=55;j++)
//            if(b.a[i][j])printf("b:%d\n",b.a[i][j]);
//    tmp[st]=1;
//    for(int i=1;i<=n;i++)
//        for(int j=1;j<=n;j++)
//            (ans[i]+=tmp[j]*b.a[j][i])%=mod;
    ans[st]=1;
    mul2(ans,b.a,ans);
    printf("%d",ans[ed]);
    return 0;
}

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int const mod=10000;
int n,m,st,ed,K,nf,ey[5];
struct Matrix{
    int a[55][55];
    Matrix operator * (const Matrix &y) const
    {
        Matrix x;
        memset(x.a,0,sizeof x.a);
        for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
                for(int j=1;j<=n;j++)
                    (x.a[i][j]+=a[i][k]*y.a[k][j])%=mod;
        return x;
    }
    Matrix(){memset(a,0,sizeof a);}//
    void init()
    {
        for(int i=1;i<=n;i++) a[i][i]=1;
    }
}s[15],b;
Matrix operator ^ (Matrix a,int k)
{
    Matrix ret; ret.init();
    while(k)
    {
        if(k&1)ret=ret*a;
        a=a*a;
        k>>=1;
    }
    return ret;
}
int main()
{
    scanf("%d%d%d%d%d",&n,&m,&st,&ed,&K);
    st++; ed++;
    for(int i=1,x,y;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        x++; y++;
        for(int j=1;j<=12;j++)
            s[j].a[x][y]=s[j].a[y][x]=1;
    }
    scanf("%d",&nf);
    for(int i=1,tt;i<=nf;i++)
    {
        scanf("%d",&tt);
        for(int j=1;j<=tt;j++)
            scanf("%d",&ey[j]),ey[j]++;
        for(int j=1;j<=12;j++)
            for(int k=1;k<=n;k++)
                s[j].a[k][ey[j%tt+1]]=0;//+1
    }
    s[13].init();
    for(int i=1;i<=12;i++)s[13]=s[13]*s[i];
    b=s[13]^(K/12);
    for(int i=1;i<=K%12;i++)b=b*s[i];
    printf("%d",b.a[st][ed]);
    return 0;
}

 

posted @ 2018-06-20 23:17  Zinn  阅读(153)  评论(0编辑  收藏  举报