zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    转:gpio_direction_output 与 gpio_set_value
    转:gpio_request
    转: 静态模式makefile中$(cobjs): $(obj)/%.o: $(src)/%.c
    转:misc_register、 register_chrdev 的区别总结
    转:aptitude 命令详解
    转:Ubuntu12.04 LTS 使用心得-开机挂载其他分区
    转:大端模式和小段模式简述
    转:C++中 #ifdef 和#endif的作用
    转:FIFO和DMA
    Camera Link 信号源板卡学习资料第153篇: 基于Sprtan6的Full(Base) Camera Link 信号源
  • 原文地址:https://www.cnblogs.com/sherrlock/p/9798909.html
Copyright © 2011-2022 走看看