• BZOJ1875: [SDOI2009]HH去散步 图上边矩乘


    这道题十分的坑……

    我作为一只连矩乘都不太会的渣渣看到这道题就只能神搜了…..

    首先说一下普通的矩乘求方案,就是高出邻接矩阵然后一顿快速幂…..

    矩乘一般就是一些秘制递推…..

    再说一下这道题,我们可以看出这小骚题有个条件就是说,不能立刻回头,这就不能用以往的了,以往的前后顺序无关,在矩阵里放的是:f[i][j]就是说第i个状态可以由第j个状态转移而来,那么我们可以看出若这个边为无向边,那么对于->*来说这个->东西可以无脑转移到*,因为*是->的合法状态也是唯几合法状态…..

    最后的答案把->到B的加起来就好了…….

    #include<cstdio>
    #include<cstring>
    #define N 25
    #define M 65
    #define P 45989
    using namespace std;
    inline int read()
    {
         int sum=0;
         char ch=getchar();
         while(ch<'0'||ch>'9')ch=getchar();
         while(ch>='0'&&ch<='9')
         {
             sum=(sum<<1)+(sum<<3)+ch-'0';
             ch=getchar();
         }
         return sum;
    }
    int a[M<<1][M<<1],b[M<<1];
    int n,m,T,A,B;
    struct Tr
    {
        int to,next,id;
    }c[M<<1];
    int head[N],t;
    inline void add(int x,int y)
    {
        c[++t].to=y;
        c[t].next=head[x];
        c[t].id=t;
        head[x]=t;
    }
    bool En[M<<1];
    inline void  look()
    {
        printf("LET US SEE B
    ");
        for(int i=1;i<=(m<<1);i++)
         printf(" %d ",b[i]);
        printf("
    ");
    }
    inline void Init()
    {
         n=read(),m=read(),T=read(),A=read()+1,B=read()+1;
         for(int i=1;i<=m;i++)
         {
            int x=read()+1,y=read()+1;
            add(x,y),add(y,x);
         }
         for(int x=1;x<=n;x++)
         {
             for(int i=head[x];i;i=c[i].next)
             {
                 int y=c[i].to;
                 if(y==B)En[c[i].id]=1;
                 int caocaocao=0;
                 for(int j=head[y];j;j=c[j].next)
                 {
                     if(c[j].to==x)
                       caocaocao++;
                     if(c[j].to!=x||(c[j].to==x&&caocaocao!=1))
                       a[c[j].id][c[i].id]=1;
                 }
             }
         }
         for(int i=head[A];i;i=c[i].next)
          b[c[i].id]=1;
    }
    int temp[M<<1][M<<1],d[M<<1];
    inline void up()
    {
          memset(d,0,sizeof(d));
          for(int i=1;i<=(m<<1);i++)
           for(int j=1;j<=(m<<1);j++)
            d[i]+=a[i][j]*b[j]%P;
          for(int i=1;i<=(m<<1);i++)
           b[i]=d[i]%P;
    }
    inline void multi()
    {
          memset(temp,0,sizeof(temp));
          for(int i=1;i<=(m<<1);i++)
           for(int j=1;j<=(m<<1);j++)
            for(int k=1;k<=(m<<1);k++)
             temp[i][j]+=a[i][k]*a[k][j]%P;
          for(int i=1;i<=(m<<1);i++)
           for(int j=1;j<=(m<<1);j++)
            a[i][j]=temp[i][j]%P;
    }
    inline void work()
    {
          T=T-1;
          while(T)
          {
              //look();
              if(T&1)up();
              T>>=1;
              multi();
          }
          int ans=0;
          for(int i=1;i<=(m<<1);i++)
           if(En[i])
            ans+=b[i];
          ans%=P;
          printf("%d",ans);
    }
    int main()
    {
        Init();
        if(T==0)
        {
          if(A==B)printf("1");
          else printf("0");
          return 0;
        }
        work();
        return 0;
    }
  • 相关阅读:
    javascript之this的深入学习
    记一次前端面试
    nodejs学习
    Javascript内置对象
    Javascript事件
    全屏滚动插件小结
    Javascript函数的深入学习
    近年来前端开发趋势,MVVM框架,Vue.js的核心思想
    Javascript的for ... in循环
    JavaScript的对象深入学习
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7168201.html
Copyright © 2020-2023  润新知