1. 程式人生 > 實用技巧 >P3758 [TJOI2017]可樂(矩陣加速)

P3758 [TJOI2017]可樂(矩陣加速)

題目描述

加里敦星球的人們特別喜歡喝可樂。因而,他們的敵對星球研發出了一個可樂機器人,並且放在了加里敦星球的11號城市上。這個可樂機器人有三種行為: 停在原地,去下一個相鄰的城市,自爆。它每一秒都會隨機觸發一種行為。現在給加里敦星球城市圖,在第00秒時可樂機器人在11號城市,問經過了tt秒,可樂機器人的行為方案數是多少?

輸入格式

第一行輸入兩個正整數NN,MM。NN表示城市個數,MM表示道路個數。

接下來MM行每行兩個整數uu,vv,表示uu,vv之間有一條道路。保證兩座城市之間只有一條路相連,且沒有任何一條道路連線兩個相同的城市。

最後一行是一個整數tt,表示經過的時間。

輸出格式

輸出可樂機器人的行為方案數,答案可能很大,請輸出對20172017取模後的結果。

題解:

假設現在有一個鄰接矩陣A,那麼A^k的意義是,A^k的第i行第j列的數字含義是從第i到j經過k步的路徑總數。

從這個角度出發,可以先把這道題的鄰接矩陣建出來,然後算這個矩陣的k次方。

最後統計A(1,i)的和就是答案。

在原地停留的情況,就是每個點和自己建一個自環即可。

自爆的情況,可以新建一個編號為0的城市,這個點除了自己外不連出邊

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
const int mod=2017;
int t;
int n,m;
struct matrix {
    int
m[40][40]; }ans,base; void init () { memset(ans.m,0,sizeof(ans.m)); for (int i=0;i<=30;i++) ans.m[i][i]=1; memset(base.m,0,sizeof(base.m)); } matrix mul (matrix a,matrix b) { matrix wjm; memset(wjm.m,0,sizeof(wjm.m)); for (int i=0;i<=30;i++) for (int j=0;j<=30;j++)
for (int k=0;k<=30;k++) wjm.m[i][j]=(wjm.m[i][j]+a.m[i][k]*b.m[k][j]%mod)%mod; return wjm; } void qpow (int p) { while (p) { if (p&1) ans=mul(ans,base); base=mul(base,base); p>>=1; } } int main () { scanf("%d%d",&n,&m); init(); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); base.m[x][y]=1; base.m[y][x]=1; } for (int i=0;i<=n;i++) base.m[i][i]=1; for (int i=1;i<=n;i++) base.m[i][0]=1; scanf("%d",&t); qpow(t); int Ans=0; for (int i=0;i<=n;i++) Ans=(Ans+ans.m[1][i])%mod; printf("%d\n",Ans); }