[bzoj4887][矩阵乘法]可乐

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

题解

这种图论求方案数图又那么小的当然矩乘啊
一开始复杂度搞错了以为是9kw的实际上是9e..然后果断敲了个暴力稳定T
由于会自爆,所以每一次矩乘都要统计一下sum
那你直接在初始矩阵末尾加一个和就ok了嘛

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int mod=2017;
int n,m,ans,T;
struct matrix
{
    int m[35][35];
    matrix(){memset(m,0,sizeof(m));}
}st,tmp,cnt;
matrix mul(matrix u,matrix v,int n,int m,int p)
{
    matrix ret;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=1;k<=p;k++)
                ret.m[i][k]=(ret.m[i][k]+u.m[i][j]*v.m[j][k])%mod;
    return ret;
}
matrix pow_mod(matrix u,int b)
{
    matrix ans;
    for(int i=1;i<=n+1;i++)ans.m[i][i]=1;
    while(b)
    {
        if(b&1)ans=mul(ans,u,n+1,n+1,n+1);
        u=mul(u,u,n+1,n+1,n+1);b>>=1;
    }
    return ans;
}
struct node
{
    int x,y,next;
}a[210];int len,last[110];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int main()
{
    scanf("%d%d",&n,&m);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        ins(x,y);ins(y,x);
    }
    st.m[1][1]=1;
    for(int i=1;i<=n;i++)
    {
        for(int k=last[i];k;k=a[k].next)tmp.m[a[k].y][i]=1;
        tmp.m[i][i]=1;
        tmp.m[i][n+1]=1;
    }
    tmp.m[n+1][n+1]=1;
    scanf("%d",&T);
    tmp=pow_mod(tmp,T+1);
    st=mul(st,tmp,1,n+1,n+1);
/*  for(int i=1;i<=T;i++)
    {
        st=mul(st,tmp,1,n,n);
        for(int i=1;i<=n;i++)ans=(ans+st.m[1][i])%mod;
    }*/
    printf("%d\n",st.m[1][n+1]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值