YZOJ P1397 奔跑的騎士 矩陣建模

2021-08-09 06:21:23 字數 1405 閱讀 2048

鏈結

題意描述:

給定一張無向圖,乙個起點乙個終點。

定義一條合法路徑為不存在任何一條滿足a->b->a的關係的子路徑。

求從起點到終點長為乙個值的路徑數。

資料範圍:

對於30%的資料,n ≤ 4,m ≤ 10,t ≤ 10。

對於100%的資料,n ≤ 20,m ≤ 60,t ≤ 2147483647,0 ≤ a,b<=n-1。

解法:

30分做法:用佇列維護走過當前長度到達的點,拓展轉移可行轉移。當長度達到定值的時候,若達到終點,則答案加一。

複雜度:最劣o(

nt)

100分做法:

由於轉移次數較多,很自然的想到可以利用矩陣表示轉移,用快速冪進行優化。

問題在於,如何用乙個矩陣表示一系列轉移?

用乙個數列表示當前走到每個點的方案數。這些數在一步操作後會發生複雜的轉移,累加到其他格仔裡面去,這正是矩陣所支援的。

若沒有合法路徑的限制?

最直觀的想法是,在矩陣中,一行表示當前點被轉移的**。若存在j->i的路徑,則ai

,j=1

。 這樣乘上乙個矩陣就表示進行了一次全部的轉移。

如果加上路徑的限制條件呢?

相當於只能「向前走」。可惜,點是不具有方向性的,所以我們把轉移物件選擇為邊。邊可以分成兩條,分別為u->v和v->u,而按照這個想法,如果存在v->k,則邊u->v可以向v->k轉移。按照這個想法我們就重新建立了乙個合法的矩陣。

#include

#include

#include

#define r register

#define mod 45989

#define ll long long

using namespace std;

struct new_nodenode[125];

int n,m,kk,a,b;

int nt;

int bs[125];

intread()

struct mat

return ret;

}

}v0,v1,ans;

void pow(int k)

}void build()

; node[++nt]=(new_node);

}for(i=0;i<=nt;++i)

}for(i=0;i<=nt;++i)v0.a[i][i]=1;

}void print()

printf("%d",sum);

}int main()

/*

void show()

*/

問題1397 最大乘積

最大乘積 描述對於n個數,從中取出m個數,如何取使得這m個數的乘積最大呢?輸入第一行乙個數表示資料組數 每組輸入資料共2行 第1行給出總共的數字的個數n和要取的數的個數m,1 n m 15,第2行依次給出這n個數,其中每個數字的範圍滿足 a i 的絕對值小於等於4。輸出每組資料輸出1行,為最大的乘積...

yzoj P1122 階乘 題解

t組資料,給出n,求出n!最右邊非零的數。對於30 的資料,n 30,t 10。對於全部的資料,n 10 2009,t 30。一道數學題 解析n!10x 最後一位數字即是結果。10x進行拆分,變成5 x 2x。怎麼除以5x呢,好辦,乘的時候含有5的倍數的一項全部不乘進去,再遞迴此過程。即 1 2 3...

YZOJ P3290 暴力 性質題

鏈結 題意描述 給定乙個h w 的網格圖,m個互不相交 定義相交為 a rec a,a recb 且 a rec a,a recb 的矩形,n個點對。當兩點可以不經過矩形相互到達時,稱這個點對合法。求合法的點對數。題解 最初的想法就是連線合法邊,對於乙個點dfs一遍,對可以到達的點用並查集維護為乙個...