• [TJOI2017][BZOJ4887]可乐 解题报告


    传送门:戳我qwq

    首先先介绍一个性质,一张图的邻接矩阵的n次方后得到,矩阵A,A(i,j)表示在图中从 i 节点出发走了 n 步,到达 j 节点的可能方案数。这里不加证明,读者可以联系矩阵乘法的性质模拟一下。

    我们考虑到机器人有爆炸的可能性,且爆炸后不能继续走动,且它可以待在原地不动。

    那么不难想到,待在原地不动的情况可以用自环来解决。

    机器人在任何一步都可能爆炸,机器人爆炸后,该状态将不对其他任何状态产生影响。

    应该有读者已经想到了,我们可以把所有点都连向一个新建的节点,且该节点没有出度,机器人爆炸实际上就相当于被发配边疆且永远不能回来(雾。

    既然已经考虑清楚,那么我们只需要对原始领接矩阵S进行改动,所有S[i][0]=1 ,S[i][i]=1 。

    然后按照文章开头介绍的性质,A=S^t。A就是我们的答案矩阵。

    机器人从1号节点出发,那么我们最终的答案就等于 。

    于是我的代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    inline void read(int &x)
    {
        x=0;int f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        x*=f;
    }
    int N;
    struct node{
        int max[35][35];
        friend node operator * (node a,node b)
        {
            node c;
            for(int i=0;i<=N;i++)
                for(int j=0;j<=N;j++)
                    c.max[i][j]=0;
            for(int i=0;i<=N;i++)
            {
                for(int j=0;j<=N;j++)
                {
                    for(int k=0;k<=N;k++)
                    {
                        c.max[i][j]+=a.max[i][k]*b.max[k][j]%2017;
                        c.max[i][j]%=2017;
                    }
                }
            }
            return c;
        }
    };
    int M,t;
    node qpow(node st,int t)
    {
        node base=st,ans;
        for(int i=0;i<=N;i++)
            for(int j=0;j<=N;j++)
                ans.max[i][j]=0;
        for(int i=0;i<=N;i++)
            ans.max[i][i]=1;
        while(t)
        {
            if(t&1)
                ans=ans*base;
            base=base*base;
            t>>=1;
        }
        return ans;
    }
    int main()
    {
        read(N);read(M);
        node st;
        for(int i=0;i<=N;i++)
            for(int j=0;j<=N;j++)
                st.max[i][j]=0;
        int u,v;
        for(int i=1;i<=M;i++)
        {
            read(u);read(v);
            st.max[u][v]=1;
            st.max[v][u]=1;
        }
        read(t);
        for(int i=1;i<=N;i++)
            st.max[i][0]=1;
        for(int i=0;i<=N;i++)
            st.max[i][i]=1;
        node ans=qpow(st,t);
        int tot=0;
        for(int i=0;i<=N;i++)
        {
            tot+=ans.max[1][i];
            tot%=2017;
        }
        printf("%d
    ",tot);
    }
    View Code
  • 相关阅读:
    队列

    Oracle 12c新特性之——TABLE ACCESS BY INDEX ROWID BATCHED
    连续三月涨势明显,PostgreSQL 将崛起?
    Oracle物理DG自动切换——Dataguard Broker配置
    MSSQL索引视图(indexed view)之简述及使用
    连续三月涨势明显,PostgreSQL 将崛起?
    Scheduler & Task & Worker & Thread & Request & Session & Connection of SQL Server
    MSSQL内存架构及管理
    MSSQL数据库后台进程(线程)
  • 原文地址:https://www.cnblogs.com/sherrlock/p/9798909.html
Copyright © 2020-2023  润新知