鏈結
題意描述:
給定一張無向圖,乙個起點乙個終點。
定義一條合法路徑為不存在任何一條滿足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一遍,對可以到達的點用並查集維護為乙個...