單調佇列 組合數統計 Gym 101102D

2022-05-01 19:24:11 字數 1579 閱讀 6199

題目大意:給你乙個n*m的矩陣,矩陣裡面的數值範圍為[1,1e9]。這個矩陣有乙個值,如果相鄰的多個數字是一樣的,那麼val += 他們的組合數,例如 1 1 1,那麼就是val就是6.

問最後這個矩陣是val是多少?

思路:我們固定右端點,先統計出上方有幾個和他數值相同的數字,並把這個定義成這個位置的高,然後每次往統計以這個點為右下角的端點數即可。然後暴力右下角就是o(n*n)

我們發現,如果要每次暴力相同的數字,那麼要知道前面有幾個數字的高度,然後o(n)的暴力一遍是可以的,但是這樣會tle

所以我們知道,如果高度是》=目前的h[i][j]的高度的,那麼我們就ans[i][j] += h[i][j] * (j - k +1),其中k為高度若是出現a[i][j] == a[i][k - 1],那麼我們就只需要ans[i][j] += ans[i][k - 1]即可

//

看看會不會爆int!陣列會不會少了一維!

//取物問題一定要小心先手勝利的條件

#include using

namespace

std;

#pragma comment(linker,"/stack:102400000,102400000")

#define ll long long

#define all(a) a.begin(), a.end()

#define pb push_back

#define mk make_pair

#define fi first

#define se second

#define haha printf("haha\n")

const

int maxn = 1000 + 5

;int

n, m;

inth[maxn][maxn], a[maxn][maxn], cnt[maxn][maxn];

intmain()

}ll res = 0

;

for (int i = 1; i <= n; i++)

else

else

break

; }

cnt[i][j] = h[i][j] * (j - p.se + 1

);

if (a[i][j] == a[i][p.se - 1]) cnt[i][j] += cnt[i][p.se - 1

]; res +=cnt[i][j];

que.push_back(p);}}

}printf(

"%lld\n

", res);

}return0;

}/*5493 3

1 2 1

1 1 1

1 1 1

ans = 25

4564

3 21 2

1 11 1

ans = 13

45609

3 22 1

1 11 1

ans = 13

*/

view code

組合數學 序列統計

題解 生成乙個長度為1 n的序列,在l,r區間中選擇數字。那麼有m r l 1個數字可以選擇,每個數字選擇的次數加起來為n,所以這是明顯的插空法。為了讓每個數字都一定會被選一次,所以左右全部 1,接下裡就是利用公式合併再盧卡斯一下了。pragma gcc optimize 2 include def...

自主命題 奇組合數個數統計

對於給定的數字 n,l,r 求在 c n l,c n c n dots,c n r 中共有多少個奇數。行號 n 從0開始計數。特別地,我們規定 c 0 0 1 資料保證 0 leq n leq 10 拿到乙個1e18的題,第一反應肯定是先打個表看看嘛。我們知道有楊輝三角 1 1 1 1 2 1 1 ...

bzoj4403 序列統計 Lucas,組合數學

求有多少個長度為n nn的單調不公升序列,且對於每個元素都 l r in l,r l,r 我們讓m r l 1 m r l 1 m r l 1,因為序列的要求起始起始不會影響結果 然後我們開始考慮,我們在長度為n nn的序列全中1序列中我們可以每次選擇乙個位置讓後面的數都加1,然後選擇的個數不能超過...