a
lgv演算法
抄一波 牛客的解釋 (wiki 沒耐心看了)
lgv 演算法 (lindström–gessel–viennot lemma)
求以上矩陣的行列式,其中 e(a,b) 是從a到b的方法數,帶入求行列式即可得到(a1,a2,...an) 到 (b1,b2,...bn) 的所有不相交路徑的種數
再看這道題,其實就是要找從(n,0)到(0,m)的兩條可重合的路徑。如何將模型轉移到不相交?
一條路往左下角移一格
a1,a2 ----- (n,0) (n-1,-1)
b1,b2------ (0,m) (-1,m-1)
e(a1,b1) = ....
ans=
b symmetric matrix
很有意思,從矩陣--關聯到鄰接矩陣(圖論)--dp
最終轉換得到的題意是:給你n個不同的點,問能組成多少不同的環
先考慮n個不同的球能組成多少不同的乙個環 即:環排列 (n-1)!
dp我是想不到的,那就走一遍吧:
dp[n] 為數量為n的情況下,有多少的環的情況
1.從n-1個點裡找出1個點 與新加的點組成乙個環
(n-1)dp[n-2]
2.從n-1個點中找出k個點 ,與新加的那個點組成乙個環
c(n-1,k) dp[n-k-1]*(k-1)!
死活推不出。。。這一數學題。
老姐推出的。不貼**了 就照著公式寫
f(n) = (n-1) *f(n-2) +sum ((n-1)!*f(k)/k!/2)
e大意:對於乙個長度為 n 的由(1-k)組成的序列,去掉m個字元的不同子串行有多少個?
由去掉m個字元組成子串行可以理解為只取(n-m)個字元組成的不同序列。
首先遇到的問題是什麼?
同乙個字串可以有多種取法,那麼如何篩除重複,就是這個問題的關鍵。
官方題解寫的很不錯。
用dp做
dp[i][j] 代表取第i個位置的數,且其中刪除了j個數的情況數
再去計算next[i][c] 代表第i個位置之後 第乙個為c的位置(不包括位置i,且若是沒有,統一為n+1)
那麼這樣一來狀態轉移方程就是什麼啊?
dp[next[i][c]] [ next[i][c]-i-1+j ] +=dp[i][j]
解釋一下(我自己都看了好久。。。人蠢就要多努力)
對於一串原序列與子串行:
例如 原 1 2 1 2 1 1 2 1
子 1 1 2 (dp[4][1] -----刪了位置2)
對於 子串行 1 1 2 它下乙個的取值有4種情況 恰好是pos 5~8,但是若是m=1(只刪除乙個)的話,pos 5,6,8就會多次記錄,所以不能從位置四一一轉移到 5 6 8,只能留乙個,留哪個?很顯然,留5,它是第乙個出現的「1」,它的末尾可以接更多的值,就像直播時的前輩說的那樣,這個有點貪心的感覺。
如何去重的呢?
看例子的位置 5 dp[5][0]=2 (11和21)怎麼得到的11和21呢?位置是35和45只考慮這個數之前的第乙個值。
之後看牛客別人的**,發現大多數人不是這樣做的,他們是如何處理的呢?
dp[i][j]代表前i個位置,刪j 個數的情況數(注意,這裡不強制要求第i個數必須取,所以答案直接就是dp[n][m])
轉移方程:
dp( i , j ) = dp( i-1, j) +dp ( i-1, j-1) //第i個數不取+第i個數取
顯然,這裡會有重複,我很好奇,他們是怎麼處理重複的?
if
(pre[i]&&pre[i]+j-i>=0)
dp[i][j]=(dp[i][j]-dp[pre[i]-1][pre[i]+j-i]+mod)%mod;
額?這波操作有點秀啊,看不懂啊!!不過怎麼這麼熟悉呢
if(pre[i]&&i-pre[i]<=j)//如果位置i的前乙個位置的數存在,並且能刪那麼多數
dp[i][j]=(dp[i][j]-dp[pre[i]-1][pre[i]+j-i]+mod)%mod;
舉例子:
1 2 3 4 3 3 2 1
到pos 5 就有問題了 序列123 13 23就會有重複了
假設在pos5前dp[i][j] 一直保持它原本的意義 那麼根據轉移式
dp[5][0] 沒重複,不用減
dp[5][1]沒重複,不用減
dp[5][2]重複出現了 且減去 dp[2][1] (對應123)
dp[5][3] 減去 dp[2][2] (對應12,13 )
dp[5][4].......都減去乙個0(因為dp越界了)
好神奇啊 為什麼啊?
有什麼神奇的,就是字面意思嘛
首先要減去的這個dp值的位置肯定是pre[i]-1因為之後才確定是哪個3嘛
那j是多少呢pre[i]+j-i
即 j -( i-pre[i] )中間都不刪啊,(有中間的元素的話,就是乙個新序列了嘛)
還有一種做法
ans[len] 代表長度為len的序列種數
nxt[len][num]代表長度為len,之後數字為num的種數
那麼 ans[len] += ans[len]-1 - nxt[len][a[i]]
dp[i][j] = ans[j-1]
//額 看不懂了,貼一下**之後消化吧
#include #include #include #include #include #define n 2000050
using namespace std;
typedef long long ll;
const int max=1e5+10;
long long dp[max][20];
const int mod= 1e9+7;
long long ans[max];
long long a[max];
int main()
for(int i=1;i<=n;i++)
ans[0]=1;
for(int i=1;i<=n;i++)
}ans[n-m]=(ans[n-m]+mod)%mod;
cout
牛客多校 Playing games FWT
給出 n n 個數a1 a2,an role presentation style position relative a1,a2,a na1,a2,a n,問最多選出多少個數使得這些數的異或和為0。n,ai 5 105 n,a i 5 105 震驚!老年退役選手居然開始寫題解了。這次回家本來也沒打...
2018牛客多校3
h diff prime pairs 1 3 1 5 1 7 1 11.2 3 2 5 2 7 2 11.3 3 3 5 3 7 3 11.4 3 4 5 4 7 4 11.打個素數表 用素數篩一遍 includeusing namespace std bool a 11111111 int zs ...
牛客多校 Ternary String (數論)
示例1輸入複製3 000012 22輸出複製3 9345 思路 1.如果遇到了 0,t 2.如果遇到了1,t t 2 2 因為之前經歷了t,那麼就會派生出來t個0,加上乙個1的時間 2 就是上式了 3.如果遇到了2,t 3 2 t 1 可以類似於2來想,經過了t後到了乙個2 會變成這樣 211010...