zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      洛谷传送门BZOJ传送门

    可乐

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 299  Solved: 207

    Description

    加里敦星球的人们特别喜欢喝可乐。因而,他们的敌对星球研发出了一个可乐机器人,并且
    放在了加里敦星球的1号城市上。这个可乐机器人有三种行为:停在原地,去下一个相邻的
    城市,自爆。它每一秒都会随机触发一种行为。现在给出加里敦星球城市图,在第0秒时可
    乐机器人在1号城市,问经过了t秒,可乐机器人的行为方案数是多少?
     

    Input

    第一行输入两个正整数N,M表示城市个数,M表示道路个数。(1≤N≤30,0≤M≤100)
    接下来M行输入u,v表示u,v之间有一条道路。
    (1≤u,v≤n)保证两座城市之间只有一条路相连。
    最后输入时间t。1<t≤10^6

    Output

     输出可乐机器人的行为方案数,答案可能很大,请输出对2017取模后的结果。

    Sample Input

    3 2
    1 2
    2 3
    2

    Sample Output

    8

    HINT

    Source


      分析:

      一道人类智慧题,思路无比妙。

      大多数人第一眼看到这题反应应该都是$DP$,出题人貌似也没想卡一般的$DP$(用$DP$+矩阵加速也是可以以非常优秀的效率过掉的),因此写的好看的$DP$也可以过,不过可能会需要吸一口氧气。

      正解是矩阵快速幂。

      嗯???矩阵快速幂??这题和矩阵快速幂有关系??是的,正解就是矩阵快速幂。juruo一开始也没想到,还是看了一位julao的思路才豁然开朗。

      首先看,$n$的范围只有$30$,明显可以用邻接矩阵。而这题的突破口就在这里。我们来思考,如果对邻接矩阵$A$做快速幂会怎样?

      从$Floyd$算法的角度分析,没有边权时(即默认所有边的边权为$1$时),$A^k$中的任意一个元$a_{i,j}$表示从$i$到$j$经过$k$条边的方案数。这个不太方便字面上解释,可以自己根据矩阵乘法的法则结合具体例子分析一下。

      对于这题,因为可以留在原地,所以我们可以把所有点都加上一个自环。还有爆炸的情况,我们可以把爆炸当作第$0$号点,并单方面建立所有点到$0$号点的单向边,这样的过的话到达$0$号点以后就不会再到其他点,就能表示出爆炸的情况了。最后统计的答案应该就是从$1$号点到所有点经过$k$条边的情况总和,也就是$sum ^n_{i=0}a[1][i]$。

      剩下的就是矩阵快速幂的模板了。

      不得不说,真是一道人类智慧题。

      Code:

      

    //It is made by HolseLee on 6th Sep 2018
    //Lougu.org P3758
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int mod=2017;
    int n,m,t,ans;
    struct Matrix {
        int a[31][31];
        Matrix() { memset(a,0,sizeof(a)); }
        Matrix(int b[31][31]) { memcpy(a,b,sizeof(a)); }
        friend Matrix operator * (const Matrix x,const Matrix y) {
            Matrix ret;
            for(int i=0; i<=30; ++i) 
            for(int j=0; j<=30; ++j) 
            for(int k=0; k<=30; ++k) {
                ret.a[i][j]=(ret.a[i][j]+(x.a[i][k]*y.a[k][j]))%mod;
            }
            return ret;
        } 
    }H,L;
    
    int main()
    {
        scanf("%d%d",&n,&m);
        int x,y;
        for(int i=1; i<=m; ++i) {
            scanf("%d%d",&x,&y);
            H.a[x][y]=H.a[y][x]=1;
        }
        for(int i=0; i<=n; ++i) H.a[i][0]=1, H.a[i][i]=1;
        for(int i=0; i<=n; ++i) L.a[i][i]=1;
        scanf("%d",&t);
        while( t ) {
            if( t&1 ) L=L*H;
            t>>=1; H=H*H;
        }
        for(int i=0; i<=n; ++i)
        ans=(ans+L.a[1][i])%mod;
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    ACM2114_S[I](1^3+2^3+3^3)
    幻源境第二十八章
    Java中间件之RMI及实例介绍 · zijian's blog
    玩转iOS开发:iOS中的GCD开发(三)
    浅谈在ES5环境下实现const
    concurrent包分析之Executor框架
    Inheritance Learning Note
    开发岗笔试基础题总结
    论文笔记[Slalom: Fast, Verifiable and Private Execution of Neural Networks in Trusted Hardware]
    logstash收集nginx日志
  • 原文地址:https://www.cnblogs.com/cytus/p/9600437.html
Copyright © 2011-2022 走看看