(矩阵快速幂) [TJOI2017]可乐

这题一看我就先想着t*m的分层图dp,dp[i][j][k]代表第t秒第j个点的路径数,k=0就是在第j个点爆炸,k=1就是停留在j点,然后

dp[i][j][1]=dp[i-1][j][1]+∑(其他相邻点v,dp[i-1][v][1]),意思是第i秒停留在第j个点的路径可以是第i-1秒停留在第j个点或和j相邻点转移过来

dp[i][j][0]=dp[i-1][j][1],意思是在第i秒第j个点爆炸的点只能是第i-1秒停留在第j个点转移来

然后把每秒爆炸的方案加上,再加上第t秒停留在每个点的方案就是答案

然后我就是开始写了。。然后样例过了。。然后我就开始交。。。然后人没了

一直t一直t,t到怀疑人生

然后我就试了下题解的分层dp代码,然后也t了,应该是加强了数据。告辞

(话说洛谷评测机真8太行,1s1e8都跑不了)

那就只能矩阵快速幂了,邻接矩阵的k次幂的到mp[][],mp[i][j]意思是第i个点到第j个点路径长度为k的走法有多少种

于是这题不就是要求点1走t次到其他点的总方案吗

不过还有两个地方要处理

1.它可以在某个点停留

那我们只要给每个点增加一个自环,那就可以达到在某个点停留的效果

2.它可以自爆

那只要给每个点和0连一条边,0本身没有出边,那每个点到0就不能出去,相当于自爆了

最后ans=  \sum_{i=0}^{n}mp[1][i],

题目描述

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

输入格式

第一行输入两个正整数 NNN,MMM。NNN 表示城市个数,MMM 表示道路个数。

接下来 MMM 行每行两个整数 uuu,vvv,表示 uuu,vvv 之间有一条道路。保证两座城市之间只有一条路相连,且没有任何一条道路连接两个相同的城市。

最后一行是一个整数 ttt,表示经过的时间。

输出格式

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

输入输出样例

输入 #1

3 2
1 2
2 3
2

输出 #1

8

说明/提示

样例输入输出 1 解释

  • 111 ->爆炸。
  • 111 -> 111 ->爆炸。
  • 111 -> 222 ->爆炸。
  • 111 -> 111 -> 111。
  • 111 -> 111 -> 222。
  • 111 -> 222 -> 111。
  • 111 -> 222 -> 222。
  • 111 -> 222 -> 333。

数据范围与约定

  • 对于 20%20\%20% 的数据,保证 t≤1000t \leq 1000t≤1000。
  • 对于100%100\%100%的数据,保证 1<t≤1061 < t \leq 10^61<t≤106,1≤N≤301 \leq N \leq301≤N≤30,0<M<1000 < M < 1000<M<100,1≤u,v≤N1 \leq u, v \leq N1≤u,v≤N。
    #include <cstdio>
    #include<iostream>
    #include<cstring>
    #include<map>
    using namespace std;
    typedef long long ll;
    const ll mod = 2017;
    map<ll,ll>mp;
    inline ll read(){
        ll x = 0;char c = 0;
        c = getchar();
        while(isdigit(c)) x = (x<<1)+(x<<3)+(c^48),c = getchar();
        return x;
    }
    struct matrix{
        ll x[31][31];
    }a;
    matrix muli(matrix a,matrix b){
        matrix temp;
        memset(temp.x,0,sizeof(temp.x));
        for(register int i = 0; i <=30; i++)
        for(register int j = 0; j <=30; j++)
        for(register int k = 0; k <=30; k++){
            temp.x[i][j]+=a.x[i][k]*b.x[k][j];
            temp.x[i][j]%=mod;
        }
        return temp;
    }
    matrix pows(matrix a,ll b){
        matrix e;
        memset(e.x,0,sizeof(e));
        for(register int i = 0; i <=30; i++) e.x[i][i] = 1;
        matrix ans = e;
        while(b){
            if(b&1) ans=muli(ans,a);
                a=muli(a,a);
            b>>=1;
        }
        return ans;
    }
    int main()
    {
        /*ll n,q;
        q = read(),n = read();
        matrix a;
        a.x[0][0] = 3;a.x[0][1] = 1;a.x[1][0] = 1;a.x[1][1] = 0;
        matrix b;
        b.x[0][0] = 3;b.x[0][1] = 1;b.x[1][0] = 2;b.x[1][1] = 0;
        ll ans = 0;
        matrix a1,b1;
        mp[0] = 0;mp[1] = 1;
        for(register ll i = 1; i <= q; i++){
            if(mp.count(n)==0){
                b1=pows(b,n-2);
                a1=muli(a,b1);
                ans=ans^a1.x[0][0];
                mp[n] = a1.x[0][0];
                n=n^(a1.x[0][0]*a1.x[0][0]);
            }else{
                ans^=mp[n];
                n^=(mp[n]*mp[n]);
            }
        }
        printf("%lld\n",ans);*/
        ll n,m;
        scanf("%lld %lld",&n,&m);
    
        for(ll i=1;i<=m;i++)
        {
            ll u,v;
            scanf("%lld %lld",&u,&v);
            a.x[u][v]=1;a.x[v][u]=1;
        }
        for(ll i=0;i<=n;i++)a.x[i][i]=1;
        for(ll i=1;i<=n;i++)
        {
            a.x[i][0]=1;
        }
        ll t;
        scanf("%lld",&t);
        matrix b=pows(a,t);
        ll ans=0;
        for(ll i=0;i<=n;i++) ans=(ans+b.x[1][i])%2017;
        printf("%lld\n",ans);
        return 0;
    }
    

猜你喜欢

转载自blog.csdn.net/qq_43497140/article/details/107089738
今日推荐