【笛卡爾樹+DP】【SP3734】 PERIODNI - Periodni
題目
題目描述
English VietnameseLuka is bored in chemistry class so he is staring at a large periodic table of chemical elements hanging from a wall above the blackboard. To kill time, Luka decided to make his own table completely different from the one in the classroom.
His table consists of N columns, each with some height, aligned at the bottom (see example below). After he draws the table he needs to fill it with elements. He first decided to enter the noble gases of which there are K. Luka must put them in the table so that no two noble gases are close to each other.
Two squares in the table are close to each other if they are in the same column or row, and all squares between them exist. In the example below, the ‘a’ squares are not close, but the ‘b’ squares are.
Write a program that, given N, K and the heights of the N columns, calculates the total number of ways for Luka to place the noble gases into the table. This number can be large, so output it modulo 1 000 000 007.
輸入格式
The first line contains the integers N and K separated by a space (1
The next line contains N positive integers, separated by spaces. These are heights of the columns from left to right. The heights will be at most 1 000 000.
輸出格式
Output the number of ways for Luka to fill his table with noble gases, modulo 1 000 000 007.
題意翻譯
給定一個N列的表格,每列的高度各不相同,但底部對齊,然後向表格中填入K個相同的數,填寫時要求不能有兩個數在同一列,或同一行,下圖中b是錯誤的填寫,a是正確的填寫,因為兩個a雖然在同一行,但它們中間的表格斷開。
輸出所有填寫方案數對1 000 000 007的餘數。
輸入: 第一行兩個整數 N 和 K (1 ≤ N ≤ 500, 1 ≤ K ≤ 500),表示表格的列數和要填寫的數的個數。 接下來一行N個數,表示每列的高度。高度不超過 1 000 000.
輸出: 一個整數,方案總數對1000 000 007的餘數。
注意: 對於 40% 的資料, 所有數值小於15. 對於70% 的資料,所有數值小於100.
Translated by @yijan
輸入輸出樣例
輸入 #1複製
5 2
2 3 1 2 4
輸出 #1複製
43
思路
顯然是先建出小根笛卡爾樹,考慮每個矩形內部的答案。
設
d
p
[
u
]
[
i
]
dp[u][i]
dp[u][i] 表示
u
u
u 子樹內放
i
i
i 個數的方案數,
d
p
1
[
i
]
dp1[i]
dp1[i] 表示 當前子樹
u
u
u 內不考慮當前矩形,放
i
i
i 個數的方案數,設
H
[
i
]
H[i]
H[i] 為當前矩陣可行高度(即
A
[
u
]
−
A
[
f
a
[
u
]
]
A[u]-A[fa[u]]
A[u]−A[fa[u]] )。
顯然有
d
p
1
[
]
=
f
[
l
s
]
∗
f
[
r
s
]
dp1[] = f[ls]*f[rs]
dp1[]=f[ls]∗f[rs] ,即左右子樹的卷積。
接下來就是揹包的轉移了,列舉當前矩形內有多少列還是空的進行轉移。
設當前子樹放置
i
i
i 個棋子,有
j
j
j 個在當前矩陣放置。
則
d
p
[
u
]
[
i
]
+
=
∑
j
=
0
i
d
p
1
[
i
−
j
]
∗
C
(
S
z
[
u
]
−
(
i
−
j
)
,
j
)
∗
C
(
H
[
x
]
,
j
)
∗
j
!
dp[u][i]+=\sum_{j=0}^idp1[i-j]*C(Sz[u]-(i-j),j)*C(H[x],j)*j!
dp[u][i]+=∑j=0idp1[i−j]∗C(Sz[u]−(i−j),j)∗C(H[x],j)∗j!
第一個組合數是列舉矩陣所剩的行,第二個組合數是列舉矩陣所剩的列。
最後乘上 j! 是因為橫縱座標是兩兩組合的,因此匹配的方案數為 j!。
程式碼
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define N 5077
#define mod 1000000007
ll n,k,top,root;
ll ls[N],rs[N],st[N];
ll f[N][N],h[N],siz[N],fac[1000050],inv[1000050];
ll qp(ll x,ll y)
{
ll ans=1;
while(y)
{
if(y&1) ans=(ans*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return ans%mod;
}
void init()
{
fac[0]=fac[1]=inv[0]=inv[1]=1;
fac[2]=2,inv[2]=qp(2,mod-2);
for(int i=3;i<=1000000;++i)
{
fac[i]=(fac[i-1]*i)%mod;
inv[i]=qp(fac[i],mod-2);
}
}
ll C(ll n,ll m)
{
if(n<m) return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int build()
{
for(int i=1;i<=n;++i)
{
while(top&&h[st[top]]>h[i]) ls[i]=st[top--];
if(top) rs[st[top]]=i;
st[++top]=i;
}
return st[1];
}
void dfs(int x,int val)
{
f[x][0]=siz[x]=1;
ll high=h[x]-val;
if(ls[x])
{
ll y=ls[x];
dfs(y,h[x]),siz[x]+=siz[y];
for(ll i=min(siz[x],k);i>=0;--i)
for(ll j=1;j<=min(siz[y],i);++j)
f[x][i]=(f[x][i]+f[y][j]*f[x][i-j]%mod)%mod;
}
if(rs[x])
{
ll y=rs[x];
dfs(y,h[x]),siz[x]+=siz[y];
for(ll i=min(siz[x],k);i>=0;--i)
for(ll j=1;j<=min(siz[y],i);++j)
f[x][i]=(f[x][i]+f[y][j]*f[x][i-j]%mod)%mod;
}
for(ll i=min(siz[x],k);i>=0;--i)
for(ll j=1;j<=min(high,i);++j)
f[x][i]=(f[x][i]+f[x][i-j]*fac[j]%mod*C(high,j)%mod*C(siz[x]-(i-j),j)%mod)%mod;
}
int main()
{
init();
read(n),read(k);
for(int i=1;i<=n;++i) read(h[i]);
root=build();
dfs(root,0);
printf("%lld",f[root][k]);
return 0;
}
相關文章
- 笛卡爾樹
- 基環樹和笛卡爾樹
- 二叉查詢樹和笛卡爾樹
- P1377 [TJOI2011] 樹的序 (笛卡爾樹)
- 笛卡爾座標張量簡介7
- 笛卡爾積的應用——商品 SKU 計算
- Python如何從列表中獲取笛卡爾積Python
- 二維陣列笛卡爾積js實現陣列JS
- 笛卡爾:語言是思想唯一確定標誌?
- 笛卡爾乘積的javascript版實現和應用JavaScript
- 笛卡爾實驗室全面遷移至亞馬遜雲科技亞馬遜
- 笨辦法學C 導言:C的笛卡爾之夢
- 【TUNE_ORACLE】列出走了笛卡爾積的SQL參考OracleSQL
- 科學的演變:從笛卡爾到生成式人工智慧人工智慧
- 形象化理解笛卡爾座標系和極座標系
- 畢設(5)—笛卡爾空間軌跡規劃(直線、圓弧)
- C++ opencv的圓轉矩形,極座標轉笛卡爾座標系C++OpenCV
- 樹形DP
- 樹形DP!
- SparkSQL中產生笛卡爾積的幾種典型場景以及處理策略SparkSQL
- 樹上染色(樹形dp)
- 流體力學守恆形式Euler方程(笛卡爾座標、柱座標、球座標)
- [筆記]樹形dp筆記
- 理解笛卡爾積在資料庫查詢中的實際應用與最佳化資料庫
- 樹上的等差數列 [樹形dp]
- [樹形dp][HAOI2015]樹上染色
- 樹形DP二三知識
- ACM日常訓練日記——8.8(二分dp,最小生成樹+克魯斯卡爾演算法和普利姆演算法)ACM演算法
- HDU 6035 Colorful Tree(樹形DP)
- 卡米黛爾系統卡米黛爾商城系統
- 最小生成樹(克魯斯卡爾演算法)資料結構演算法資料結構
- LG P3233 [HNOI2014]世界樹(虛樹,dp)
- 熟練剖分(tree) 樹形DP
- 卡爾曼濾波
- 笛卡爾空間力反饋的關節速度控制之機器人運動學庫KDL安裝及使用機器人
- ZROJ#398. 【18提高7】隨機遊走(期望dp 樹形dp)隨機
- WeetCode4 —— 二叉樹遍歷與樹型DP二叉樹
- UVA 1220 Party at Hali-Bula (樹形DP)