zoukankan      html  css  js  c++  java
  • 洛谷P3758 [TJOI2017]可乐

    原题链接:洛谷P3758 [TJOI2017]可乐 

    题目描述

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

    输入输出格式

    输入格式:

    第一行输入两个正整数况N,M,N表示城市个数,M表示道路个数。(1 <= N <=30,0 < M < 100)

    接下来M行输入u,v,表示u,v之间有一条道路。(1<=u,v <= n)保证两座城市之间只有一条路相连。

    最后输入入时间t

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    3 2
    1 2
    2 3
    2
    输出样例#1: 复制
    8

    说明

    【样例解释】

    1 ->爆炸

    1 -> 1 ->爆炸

    1 -> 2 ->爆炸

    1 -> 1 -> 1

    1 -> 1 -> 2

    1 -> 2 -> 1

    1 -> 2 -> 2

    1 -> 2 -> 3

    【数据范围】

    对于20%的pn,有1 < t ≤ 1000

    对于100%的pn,有1 < t ≤ 10^6。

    题解

    题意:给定一个无向图,一个机器人每一秒可以留在原地,自爆或走一步,求在t秒内机器人所有行动的可能性

    算法:邻接矩阵+矩阵乘法

    建模:图直接建,留在原地则让每一个点向自己连边,自爆则设一个点为爆炸,每一个点向爆炸点连边(爆炸点向自己连边)

    base.m[0][0]=1;
    for(int i=1;i<=L;i++){
        base.m[i][i]=base.m[i][0]=1;
    }
    for(int i=1;i<=M;i++){
        int ii,jj;
        scanf("%d%d",&ii,&jj);
        base.m[ii][jj]=base.m[jj][ii]=1;
    }

    设f[i][j][t]为从i到j进过t秒的行动方案数,类似于Floyd的转移,有f[i][j][t1+t2]=∑f[i][k][t1]+f[k][j][t1]

    设f[][][x]为f[x],故矩阵f[t1+t2]=f[t1]*f[t2],即可用矩阵乘法,而此题答案就为f[1]t,矩阵快速幂即可

    矩阵乘法及快速幂:

    inline matrix operator*(matrix x,matrix y){
        matrix ret;
        for(int i=0;i<=L;i++){
            for(int j=0;j<=L;j++)
                for(int k=0;k<=L;k++)
                    ret.m[i][j]=(ret.m[i][j]+x.m[i][k]*y.m[k][j])%MOD;
        }
        return ret;
    }
    inline matrix operator^(matrix x,int p){
        matrix ret;
        ret.build();
        while(p){
            if(p&1)
                ret=ret*x;
            x=x*x;
            p>>=1;
        }
        return ret;
    }
    View Code

    核心代码:

    ans=(base^T);
    LL sum=0;
    for(int i=0;i<=L;i++){
      sum=(sum+ans.m[1][i])%MOD;
    }

    完整代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int MOD=2017,MAXL=32;
     5 int L,M,T;
     6 struct matrix{
     7     LL m[MAXL][MAXL];
     8     matrix(){
     9         memset(m,0,sizeof(m));
    10     }
    11     inline void build(){
    12         memset(m,0,sizeof(m));
    13         for(int i=0;i<=L;i++)
    14             m[i][i]=1;
    15     }
    16     inline void print(){
    17         for(int i=0;i<=L;i++,putchar('
    '))
    18             for(int j=0;j<=L;j++)
    19                 printf("%lld ",m[i][j]);
    20         putchar('
    ');
    21     }
    22 };
    23 inline matrix operator*(matrix x,matrix y){
    24     matrix ret;
    25     for(int i=0;i<=L;i++){
    26         for(int j=0;j<=L;j++)
    27             for(int k=0;k<=L;k++)
    28                 ret.m[i][j]=(ret.m[i][j]+x.m[i][k]*y.m[k][j])%MOD;
    29     }
    30     return ret;
    31 }
    32 inline matrix operator^(matrix x,int p){
    33     matrix ret;
    34     ret.build();
    35     while(p){
    36         if(p&1)
    37             ret=ret*x;
    38         x=x*x;
    39         p>>=1;
    40     }
    41     return ret;
    42 }
    43 int main(){
    44     scanf("%d%d",&L,&M);
    45     matrix ans,base;
    46     ans.build();
    47     base.m[0][0]=1;
    48     for(int i=1;i<=L;i++){
    49         base.m[i][i]=base.m[i][0]=1;
    50     }
    51     for(int i=1;i<=M;i++){
    52         int ii,jj;
    53         scanf("%d%d",&ii,&jj);
    54         base.m[ii][jj]=base.m[jj][ii]=1;
    55     }
    56     scanf("%d",&T);
    57     ans=(base^T);
    58     LL sum=0;
    59     for(int i=0;i<=L;i++){
    60         sum=(sum+ans.m[1][i])%MOD;
    61     }
    62     printf("%lld",sum);
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    物理-接触力:百科
    物理-二力平衡:百科
    物理-摩擦力:百科
    物理-电磁力/静电力:百科
    物理-重力:百科
    化学-分子间作用力:百科
    物理-分子力:百科
    物理-斥力:百科
    物理-粒子/能量-衰变:百科
    物理-超光速:百科
  • 原文地址:https://www.cnblogs.com/guoshaoyang/p/10853573.html
Copyright © 2011-2022 走看看