2024牛客多校1

瑞雪兆丰年`發表於2024-07-21

2024牛客多校1

2024年第一場多校賽,打的很一般,多校之前vp的幾場多校成績還不錯,一場比賽直接打回原形。

賽時隊友做的簽到題C、H,吃了兩發罰時,我自己推的A,出的很快,可惜沒注意取模,吃了發罰時,長個記性吧。

A

給定n,m,p,問長度為n,並且都由小於 \(2 ^ m\) 的陣列成,存在一個子序列的按位且等於1的序列有多少種。

假設n個數中,有k個數為奇數,那麼對於其他 \(n - k\) 個偶數,他們的高 \(m - 1\) 位就可以隨便選了。對於這k個奇數,要保證每一位這k個數中至少有一個是0。最後答案就為

\[\sum_{k = 1} ^ n C(k, n)(2 ^ {k - 1}) ^ {m - 1}2 ^ {(n - k)(m - 1)} \]

其中每項依次代表,挑選k個奇數,奇數的每一位至少有1個0的方案數,有m-1位,偶數除最低位,其他任選的方案數

B

B題是A題的hard版本,將A中的至少一個子序列改為至少兩個子序列

那麼一個很直觀的方法就是求出只存在一個子序列的方案數有多少種,在用A中的減去即可

首先是兩個結論:
1、如果一個子序列按位且等於1,那麼再添上任意一個奇數,那麼得到的新序列按位且還等於1。
2、如果一個序列按位且等於1,且他沒有按位且等於1的子序列,那麼這個序列中每個數都有一位是0,且序列中其他數該位都是1。

我們第二個結論中該數的0位成為特殊位,那麼我們就要保證每一個數都至少有1個特殊位。考慮使用do求一個奇數序列每個數都有關鍵位的方案數。 \(f[i][j]\) 代表j個數i個特殊位的情況。那麼在不考慮吧這j個數的順序的情況,轉移方程為

\[f[i][j] = f[i - 1][j - 1] + j * f[i - 1][j] \]

我們可以新填一個數,並給這個數一個新的特殊位,也可以把這個特殊位,分給原有的j個數其中之一。

有了j個數i個特殊位的方案數之後我們還需要做些什麼呢?順序問題!因為這j個數每個數都有屬於自己獨特的特殊位,所以他們必然兩兩不同,那麼他們放入序列中的順序問題,直接去乘全排列就好。還有什麼呢?對於這j個數,他們只是擁有i個特殊位,這i個特殊位還需要從m-1位中挑選出來。這i個特殊位,擁有他們的數這一位是0,其他數全是1,那麼其他m-1-i位需要放什麼呢?首先肯定不能全1,如果全1這些奇數按位且就不等於1了。其次這些數也不能只有一個1,如果只有一個1,這些數的特殊位就會變多,會和特殊位更多的情況干擾。所以每一位的方案數就是 \(2^k-1-k\) 。再列舉一些奇數的個數這題就結束了,好了上一下程式碼吧。程式碼只供參考

void solve() {
	for (int i = 2; i <= n; i++) { // 列舉奇數個數
		i64 t = qpow(2ll, i);
		i64 res = qpow((t - 1 + p) % p, m - 1);
		i64 k = ((t - 1 - i ) % p + p) % p;
		for (int j = 1; j <= m - 1; j++) {
			pw[j] = pw[j - 1] * k % p; // 求非特殊位的方案數
		}
		for (int j = i; j <= m - 1; j++) { // 列舉特殊位個數
			res -= c[m - 1][j] * f[j][i] % p * fac[i] % p * pw[m - 1 - j] % p;
			res = (res % p + p) % p;
		}
		res = res * c[n][i] % p * qpow(2ll, (n - i) * (m - 1) % p) % p;
		ans = (ans + res) % p;
	}
}

D

給定一個初始為空的序列,q次操作,每次操作兩個數t,v,代表刪除序列最後一個數t次,並將v加入序列,輸出該序列所有字尾和的異或和。

首先第一個很巧妙的思想就是將字尾和轉化為字首和,對於從i到n的字尾和,我們可以用 \(S_n - S_i\)表示,第二個思想就是判斷一個數第i位是否位1,我們可以看

相關文章