• [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。



    这道题我们可以从邻接矩阵的幂的意义考虑。

    设现在有一个邻接矩阵AA。

    那么A^kAk的意义是什么?(两个点之间若有边则A[u][v]=1A[u][v]=1)

    floydfloyd算法的角度考虑,不难发现A^kAk的第ii行第jj列的数字含义是从ii到jj经过kk步的路径方案总数。

    从这个角度考虑,这个点就有了一种做法。

    首先将这个图的邻接矩阵建出来,然后直接算这个矩阵的kk次方。

    最后统计sumlimits_{i=1}^{n}A[1][i]i=1nA[1][i]就是答案。

    那么在原地停留和自爆怎么处理?

    在原地停留很简单,我们只要认为每个点都有一个从自己到自己的自环即可。

    那自爆呢?

    我们可以将自爆这个状态也看成一个城市,就设它为编号00。

    我们在邻接矩阵上从每个点都向这个点连一条边,这个点除了自己外不连其他出边。

    这样就满足了任何一个点随时可以自爆,且无法恢复到其他状态。

    最后,统计答案。



     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cctype>
     5 #include<cmath>
     6 #include<iostream>
     7 #include<algorithm>
     8 #include<vector>
     9 #include<set>
    10 #include<map>
    11 #include<queue>
    12 #include<stack>
    13 typedef long long ll;
    14 typedef unsigned long long ull;
    15 using namespace std;
    16 const int P=2017;
    17 struct Matrix{
    18     int a[31][31];
    19     inline Matrix operator * (const Matrix &rhs)
    20     {
    21         Matrix ret;
    22         memset(&ret,0,sizeof ret);
    23         for(int i=0;i<=30;i++)
    24             for(int j=0;j<=30;j++)
    25                 for(int k=0;k<=30;k++)
    26                     (ret.a[i][j]+=a[i][k]*rhs.a[k][j]%P)%=P;
    27         return ret;
    28     }
    29 }mp;
    30 Matrix ksm(Matrix &a,int b)
    31 {
    32     Matrix ret;
    33     memset(&ret,0,sizeof ret);
    34     for(int i=0;i<=30;i++) ret.a[i][i]=1;
    35     while(b)
    36     {
    37         if(b&1) ret=ret*a;
    38         a=a*a;b>>=1;
    39     }
    40     return ret;
    41 }
    42 int u,v,n,m,t;
    43 int main()
    44 {
    45     scanf("%d%d",&n,&m);
    46     for(int i=1;i<=m;i++)
    47     {
    48         scanf("%d%d",&u,&v);
    49         mp.a[u][v]=1;mp.a[v][u]=1;
    50     }
    51     for(int i=0;i<=n;i++)
    52         mp.a[i][i]=1;
    53     for(int i=1;i<=n;i++) mp.a[i][0]=1;
    54     int ans=0;
    55     scanf("%d",&t);
    56     Matrix anss=ksm(mp,t);
    57     for(int i=0;i<=n;i++) (ans+=anss.a[1][i])%=P;
    58     printf("%d
    ",ans);
    59 }
  • 相关阅读:
    Idea中Module is not specified解决办法
    Navicat 导入数据时报Incorrect datetime value: '0000-00-00 00:00:00.000000' 错误
    SQL Server错误18456,window身份验证登录失败解决办法
    Linq
    web.config配置数据库连接
    $.ajax()方法详解
    将一张图片上传到指定的文件夹,然后在窗体上的PictrueBox控件中显示出来
    winform中picturebox自适应图片大小
    C#中产生SQL语句的几种方式
    [转]ORACLE触发器详解
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10336004.html
Copyright © 2020-2023  润新知