洛谷P7112 行列式求值

2022-09-22 00:30:11 字數 4962 閱讀 7811

這是乙個讓你掉頭髮的模板題

行列式 (\(\texttt\)) 是乙個函式定義,取值是乙個標量。

對乙個 \(n\times n\) 的矩陣 \(a\)(\(n\) 階方陣),其 \(n\) 階行列式寫作 \(\det(a)\) 或者 \(|a|\),定義為:

\[\det(a)=|a|=\sum_p(-1)^\prod_^n a_

\]\(p\) 表示乙個排列,所有可能的 \(p\) 則是 \(1\) 到 \(n\) 這 \(n\) 個數的全排列。\(\tau(p)\) 表示乙個排列 \(p\)逆序對個數

\[\begin18 & 5 & 1 \\12 & 2 &3 \\4& 2 & 1\end

\]我們今天的問題,僅限於如何把行列式的值求出來

我們發現 \(\tau(p)\) 的奇偶性對行列式求值起到了很大的影響,所以我們需要了解排列的奇偶性相關。

交換對應矩陣的 \(2\) 行(列),行列式的值取反

\(\begin a_ &a_ &\cdots &a_\\\ a_ &a_ &\cdots &a_\\\ \vdots &\vdots &\ddots &\vdots\\\ a_ &a_ &\cdots &a_\\\ a_ &a_ &\cdots &a_\\\ \vdots &\vdots &\ddots &\vdots\\\ a_&a_&\cdots&a_\\\ \end = -\begin a_ &a_ &\cdots &a_\\\ a_ &a_ &\cdots &a_\\\ \vdots &\vdots &\ddots &\vdots\\\ a_ &a_ &\cdots &a_\\\ a_ &a_ &\cdots &a_\\\ \vdots &\vdots &\ddots &\vdots\\\ a_&a_&\cdots&a_\\\ \end\)

(注意右邊的矩陣,只有中間那兩行是換了位置的,其餘都沒換位置)

證明如下:

設左邊的行列式為a,右邊為b求行列式的式子長這樣:

\[\det(a)=|a|=\sum_p(-1)^\prod_^n a_

\]我們對上面的式子做一點細微的修改,把它改成求\(det(b)\)

我們能不能構造乙個排列q,使得排列q是利用某種神秘力量,從排列p轉化而來,這樣就能用a的值來代替b了?

就像這樣:

\[\det(b)=\sum_p(-1)^\prod_^n b_ \ ?\ \sum_q(-1)^\prod_^n a_

\]當然可以。p和q的區別,僅在於第k位和第k+1位被換了位,這樣就有\(b_=a_\)了!代價是\(\tau(p)=-\tau(q)\)

則有:\[\det(b)=\sum_p(-1)^\prod_^n b_ = \sum_q(-1)^\prod_^n a_=-det(a)

\]行列式的行(列)所有元素等比例變化,則行列式的值也等比例變化:

我們用乘法分配律,即可證明這個性質

如果行列式對應矩陣 \(a\) 中有一行(列),是對應 \(2\) 個矩陣 \(b,c\) 中分別的 \(2\) 行(列)所有元素之和。那麼有 \(\det(a)=\det(b)+\det(c)\);

我們可以對每個\(b_i,?+c_i,\)進行乘法分配律,來完成證明

證明如下

$\begin a_ &a_ &\cdots &a_\\ a_ &a_ &\cdots &a_\\ \vdots &\vdots &\ddots &\vdots\\ a_ &a_ &\cdots &a_\\ \vdots &\vdots &\ddots &\vdots\\ k\times a_ &k\times a_ &\cdots &k\times a_\\ \vdots &\vdots &\ddots &\vdots\\ a_&a_&\cdots&a_\\ \end=k\times \begin a_ &a_ &\cdots &a_\\ a_ &a_ &\cdots &a_\\ \vdots &\vdots &\ddots &\vdots\\ a_ &a_ &\cdots &a_\\ \vdots &\vdots &\ddots &\vdots\\ a_ & a_ &\cdots & a_\\ \vdots &\vdots &\ddots &\vdots\\ a_&a_&\cdots&a_\\ \end $

設右邊的矩陣為\(a'\),由於存在兩行相同,我們交換兩行後可以得到\(-a'\),且\(-|a'|=|-a'|\)

得\(|a'|=0,|a|=0\times |a'|=0\)

如圖所示:這是乙個三角行列式

$\begin \colora_ & \colora_ &

\colora_ & \color\cdots &\colora_ &a_\\ 0 &

\colora_ & \colora_ & \color\cdots

&\colora_ &a_\\ 0 &0 &\color a_ &\color

\cdots &\colora_ &a_\\ \color\vdots & \color\vdots

& \color\vdots & \color\ddots &\color \vdots &\vdots\\ 0 &0 &

0 & \color\cdots &\colora_ &a_\\ 0 & 0 & 0 & \cdots

&0 &a_\\ \end $

三角行列式的值非常好求: \(|a|=\displaystyle\prod_^na_\)

這一條式子很好證明:

我們考慮乙個情況,當乙個矩陣任意乙個位置出現 \(0\),其對行列式的影響非常大。

因為我們考慮公式中 \(\displaystyle\prod_^n a_\) 一項,一旦選到 \(0\) 整個 \(p\) 在

\(\displaystyle \sum_p\) 中就沒有貢獻了。

在求行列式值時,序列p不指向對角線上元素時,是不是一定會選到0呢?

下面開始進入正題

我會暴力!

直接根據定義計算,行列式求值是 \(\theta(n\times n!)\) 的。

有了上面七個性質,我們有辦法加快運算嗎?

我們考慮乙個情況,當乙個矩陣任意乙個位置出現 \(0\),其對行列式的影響非常大。

因為我們考慮公式中 \(\displaystyle\prod_^n a_\) 一項,一旦選到 \(0\) 整個 \(p\) 在

\(\displaystyle \sum_p\) 中就沒有貢獻了。

下面進入大膽猜想:

我們能不能對原行列式a進行一系列的變換,使得它變成乙個三角行列式,像下面這樣?

\(a=\begin a_ & a_ & a_ & \cdots &a_\\\ a_ &

a_ & a_ & \cdots &a_\\\ a_ & a_ & a_ & \cdots

&a_\\\ \vdots & \vdots & \vdots & \ddots & \vdots\\\ a_ & a_ &

a_ & \cdots &a_\\\ \end\)

\(\rightarrow\)

\(\begin a』_

& a『_ & a』_ & \cdots &a『_\\\ 0 & a』_ & a『_ & \cdots

&a_\\\ 0 & 0 & a』_ & \cdots &a『_\\\ \vdots & \vdots &

\vdots & \ddots & \vdots\\\ 0 & 0 & 0 & \cdots &a』_\\\ \end\)

這個三角行列式,怎麼和高斯消元,完成加減消元時的矩陣很像?

我們能不能像高斯消元中加減消元一樣,利用行列式第\(i\)行的資訊,把第\(i+1\)到\(n\)行中\(a[i]\)變為0

**長這樣:

double sol()

} }for(int i=1;i<=n;i++) res*=a[i][i];

return res;

}

但是,此題要求你取模,模的數甚至不是質數?還乘不了逆元?

我們可以把除or乘逆元,換成輾轉相除?像這樣:

\[\begin18 & 5 & 1 \\12 & 2 &3 \\4& 2 & 1\end=-\begin12 & 2 &3 \\18 & 5 & 1 \\4& 2 & 1\end=-\begin12 & 2 &3 \\6 & 3 & -2 \\4& 2 & 1\end=\begin6 & 3 & -2 \\12 & 2 &3 \\4& 2 & 1\end=\begin6 & 3 & -2 \\0 & -4 &-1 \\4& 2 & 1\end

\]我們成功在\(a[2][1]\)處製造了乙個0出來!!

通過這樣的方式,我們就可以在p不為質數的時候,把這個行列式安全地化為三角行列式

消元操作是 \(\theta(n^3)\) 的,輾轉相除法是 \(\theta(\log p)\)的,因為輾轉相除和消元每次必然使得數變小,勢能只會減少,所以這個是均攤到 \(\theta(n^2)\) 的,最終複雜度為 \(\theta(n^2\log

n+n^3)\)。

#include#define inl inline

#define ll long long

using namespace std;

const int n=605;

int n,a[n][n],mod;

inl int read()

inl int sol()

swap(a[i],a[j]);w=-w;

}//對第 i 行和第 j 行做輾轉相減。

swap(a[i],a[j]);w=-w;

} }for(int i=1;i<=n;i++)res=1ll*a[i][i]*res%mod;

res=1ll*w*res;

return (res+mod)%mod;

}int main()

洛谷P7112 行列式求值

這是乙個讓你掉頭髮的模板題 行列式 texttt 是乙個函式定義,取值是乙個標量。對乙個 n times n 的矩陣 a n 階方陣 其 n 階行列式寫作 det a 或者 a 定義為 det a a sum p 1 prod n a p 表示乙個排列,所有可能的 p 則是 1 到 n 這 n 個數...

洛谷 P1645 序列

炒雞明顯的貪心題,主要就想讓一段區間與另一段裡面重合的數越多越好。於是先按照區間右端排序,然後盡可能的把數都往右靠攏,最後與另一段區間的前面的重合。然後可以用個flag來記錄哪些數被選了什麼的。include includeusing namespace std const int maxn 100...

洛谷 P1631 序列合併

題目描述 有兩個長度都是n的序列a和b,在a和b中各取乙個數相加可以得到n 2個和,求這n 2個和中最小的n個。輸入輸出格式 輸入格式 第一行乙個正整數n 第二行n個整數ai,滿足ai ai 1且ai 10 9 第三行n個整數bi,滿足bi bi 1且bi 10 9.資料規模 對於50 的資料中,滿...