1. 程式人生 > >矩陣乘法專題1——bzoj 1297 [SCOI2009] 迷路題解

矩陣乘法專題1——bzoj 1297 [SCOI2009] 迷路題解

【原題】

1297: [SCOI2009]迷路

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 539  Solved: 367
[Submit][Status]

Description

windy在有向圖中迷路了。 該有向圖有 N 個節點,windy從節點 0 出發,他必須恰好在 T 時刻到達節點 N-1。 現在給出該有向圖,你能告訴windy總共有多少種不同的路徑嗎? 注意:windy不能在某個節點逗留,且通過某有向邊的時間嚴格為給定的時間。

Input

第一行包含兩個整數,N T。 接下來有 N 行,每行一個長度為 N 的字串。 第i行第j列為'0'表示從節點i到節點j沒有邊。 為'1'到'9'表示從節點i到節點j需要耗費的時間。

Output

包含一個整數,可能的路徑數,這個數可能很大,只需輸出這個數除以2009的餘數。

Sample Input

【輸入樣例一】
2 2
11
00

【輸入樣例二】
5 30
12045
07105
47805
12024
12345


Sample Output

【輸出樣例一】
1

【樣例解釋一】
0->0->1

【輸出樣例二】
852

HINT

30%的資料,滿足 2 <= N <= 5 ; 1 <= T <= 30 。
100%的資料,滿足 2 <= N <= 10 ; 1 <= T <= 1000000000 。

Source

Day2


【分析】首先有一個常識:如果沒有路徑長度的要求,且

給定的鄰接矩陣只有0和1表示通與不通的話,從S->E走N次的方案數就是這個矩陣自乘N次後的(S,E)的數值。

我們觀察到了一個細節:路徑長度範圍很小,只有0~9,而且N的範圍也很小,只有10。

那麼我們可以來拆點。什麼意思呢?就是把一個點拆成9個,根據路徑的長度來連邊。比如路徑長度為5,我們就用5條邊來連線。構圖夠好後就是裸的矩陣乘法了。

【程式碼】

#include<cstdio>
#include<cstring>
using namespace std;
const int mod=2009;
struct matrix
{
  int p[105][105],n;
}ans,a;
matrix operator * (matrix a,matrix b)
  {
    matrix c;c.n=a.n;
    memset(c.p,0,sizeof(c.p));
    for (int i=1;i<=a.n;i++)
      for (int j=1;j<=b.n;j++)
        for (int k=1;k<=a.n;k++)  
          c.p[i][j]=(c.p[i][j]+a.p[i][k]*b.p[k][j]%mod)%mod;
    return c;
  }
char s[50];
int i,n,T,j,k,tot;
matrix quick(int b)
{
  matrix res;res.n=a.n;
  for (int i=1;i<=a.n;i++)
    res.p[i][i]=1;
  while (b)
  {
    if (b&1) res=res*a;
    b>>=1;a=a*a;
  }
  return res;
}
int main()
{
  scanf("%d%d",&n,&T);a.n=n*9;
  for (i=1;i<=n;i++)
    for (j=1;j<=8;j++)
      a.p[9*(i-1)+j][9*(i-1)+j+1]=1;   //點的內部連邊
  for (i=1;i<=n;i++)
  {
    scanf("%s",s);
    for (j=1;j<=n;j++)
      if (s[j-1]>'0') 
        a.p[9*(i-1)+s[j-1]-48][9*(j-1)+1]=1;  //點的外部連邊
  }
  ans=quick(T);
  printf("%d",ans.p[1][n*9-8]);
  return 0;

相關推薦

矩陣乘法專題1——bzoj 1297 [SCOI2009] 迷路題解

【原題】 1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 539  Solved: 367 [Submit][Status] Description windy在有向圖中迷路了。

[BZOJ 1297][SCOI2009]迷路

www. int sed 產生 emc class play log 多少 1297: [SCOI2009]迷路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1418 Solved: 1017[Submit][St

[Luogu P4159] [BZOJ 1297] [SCOI2009]迷路

洛谷傳送門 BZOJ傳送門 題目描述 windy在有向圖中迷路了。 該有向圖有 N N N

cuda編程-矩陣乘法1

return mac cpu ims iostream oba 簡單的 oid memory 本方法采用簡單的單線程計算每組行和列乘加運算 代碼如下: #include <stdio.h> #include <stdlib.h> #include

BZOJ 1297」「SCOI 2009」迷路矩陣乘法

per 題解 algo code namespace sin 有向圖 line [1] 題意 邊權\(w \in [1, 9]\)的\(n\)個結點的有向圖,圖上從\(1\)到\(n\)長度為\(d\)的路徑計數,\(n \leq 10\). 題解 如果邊權為\(1\)很經

【bzoj1297】[SCOI2009]迷路 矩陣乘法

時間復雜度 brush 時間 col 表示 data 接下來 con pan 題目描述 給出一個 $n$ 個點的有向圖,每條邊的權值都在 $[1,9]$ 之間。給出 $t$ ,求從 $1$ 到 $n$ ,經過路徑邊權和恰好為 $t$ 的方案數模2009。 輸入 第一行

[luogu4159 SCOI2009] 迷路(矩陣乘法)

n) std 利用 efi ret etc main string stream 傳送門 Solution 矩陣乘法新姿勢qwq 我們知道當邊權為1是我們可以利用矩陣快速冪來方便的求出路徑數 那麽對於邊權很小的時候,我們可以將每個點都拆成若幹個點 然後就將邊權不為1轉化為邊

LUOGU P4159 [SCOI2009]迷路(矩陣乘法)

span clear www. log oid 長度 truct lin scan 傳送門 解題思路   以前bpw講過的一道題,順便復習一下矩陣乘法。做法就是拆點,把每個點拆成\(9\)個點,然後挨個連邊。之後若\(i\)與\(j\)之間的邊長度為\(x\),就讓\(i\

[BZOJ1297][SCOI2009]迷路(拆點+矩陣乘法

題目描述 傳送門 題解 由於矩陣的冪只能處理邊權為1的情況,又由於邊權最大隻到9,可以將一個點拆成9個點,分別表示路徑的分段長度。 比如說1->2,5 求矩陣的冪即可。 程式碼

[BZOJ 2738]矩陣乘法

mes nbsp pda splay 樹狀 getc ++ 矩陣乘法 array [BZOJ 2738]矩陣乘法 題目 給你一個N*N的矩陣,不用算矩陣乘法,但是每次詢問一個子矩形的第K小數。 INPUT 第一行兩個數N,Q,表示矩陣大小和詢問組數;接下來N行N

BZOJ 1009--GT考試(KMP&DP&矩陣乘法)

color efi namespace highlight long 情況 ref urn scanf     RP++ 題目鏈接:     http://www.lydsy.com/JudgeOnline/problem.php?id=1009 Solution

【Codeforces 506E】Mr.Kitayuta’s Gift&&【BZOJ 4214】黃昏下的禮物 dp轉有限狀態自動機+矩陣乘法優化

合數 現在 子序列 pri blue gre () div while 神題……胡亂講述一下思維過程……首先,讀懂題.然後,轉化問題為構造一個長度為|T|+n的字符串,使其內含有T這個子序列.之後,想到一個簡單的dp.

BZOJ 3326】[Scoi2013]數數 數位dp+矩陣乘法優化

spa void pla color calc() class fin 左右 明顯 挺好的數位dp……先說一下我個人的做法:經過觀察,發現這題按照以往的思路從後往前遞增,不怎麽好推,然後我就大膽猜想,從前往後推,發現很好推啊,維護四個變量,從開始

BZOJ1297 [SCOI2009]迷路矩陣優化dp】

return 必須 pan 但是 stream names mem urn cout 題目 windy在有向圖中迷路了。 該有向圖有 N 個節點,windy從節點 0 出發,他必須恰好在 T 時刻到達節點 N-1。 現在給出該有向圖,你能告訴windy總共有多少種不同的路徑

bzoj 1706: [usaco2007 Nov]relays 奶牛接力跑【矩陣乘法+Floyd】

mes AD etc err 一次 鄰接矩陣 a* 是把 for 唔不知道怎麽說……大概核心是把矩陣快速冪的乘法部分變成了Floyd一樣的東西,非常之神 首先把點離散一下,最多有200個,然後建立鄰接矩陣,a[u][v]為(u,v)之間的距離,沒路就是inf 然後註意重載乘

bzoj1297 [SCOI2009]迷路——拆點+矩陣快速冪

str ons 簡單 color pri nbsp target string php 題目:https://www.lydsy.com/JudgeOnline/problem.php?id=1297 一看感覺是矩陣快速冪之類的,但邊權不好處理啊; 普通的矩陣快速冪只能處理

bzoj 1875 [SDOI2009]HH去散步 矩陣乘法

不能 ack read class for har ans sin clear 題面 題目傳送門 解法 如果沒有不能經過上一次經過的邊這個限制,顯然就是矩陣乘法的裸題 那麽我們考慮轉化一下,把邊當成點 將一條無向邊拆成2條有向邊,然後連邊,設鄰接矩陣為\(A\) 將\(A\

【BZOJ1297】[SCOI2009]迷路矩陣快速冪)

class com ble cpp pre http 時間 new memset 【BZOJ1297】[SCOI2009]迷路(矩陣快速冪) 題面 BZOJ 洛谷 題解 因為邊權最大為\(9\),所以記錄往前記錄\(9\)個單位時間前的、到達每個點的方案數就好了,那麽矩陣大

bzoj 4162 shlw loves matrix II - 行列式 - 矩陣乘法 - 高斯消元

題目大意: 給一個nn的矩陣A,求其k次方。 n ≤ 50

B1297 [SCOI2009]迷路 矩陣

這個題我覺得很有必要寫一篇部落格。首先,我們需要知道,假如一個鄰接矩陣只有0/1構成,那麼它自己的n次方就是走n步之後的方案數。但這個題還有2~9咋辦呢。我們觀察發現,這個題只有10個點,而且邊權<=9我們可以想到拆點這個小操作。把每個點拆成9個點,點內連1的邊,點外分別連到相應的權值就行了。 題幹: