ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷P3758 [TJOI2017]可乐

2019-05-12 20:49:23  阅读:372  来源: 互联网

标签:洛谷 matrix int 机器人 样例 t1 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('\n'))
18             for(int j=0;j<=L;j++)
19                 printf("%lld ",m[i][j]);
20         putchar('\n');
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

 

标签:洛谷,matrix,int,机器人,样例,t1,P3758,TJOI2017,可乐
来源: https://www.cnblogs.com/guoshaoyang/p/10853573.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有