dp
對於乙個排列,考慮相鄰的兩個元素,如果後面乙個比前面乙個大,表示這個位置是上公升的,用 i 表示,反之這個位置是下降的,用 d表示。如排列 3,1,2,7,4,6,5 可以表示為 diidid。 現在給出乙個長度為 n-1的排列表示,問有多少種 1 到n 的排列滿足這種表示。
乙個字串 s,s 由 i,d,?組成。?表示這個位置既可以為 i,又可以為 d
對於 20%的資料,s 長度 ≤ 10;
對於 100%的資料,s長度 ≤ 1000。
有多少種排列滿足上述字串。輸出排列數模 1000000007。
?d這是一道比較裸的動態規劃題目,dp[i][j]表示前 i 位數中,最後一位為第 j 大的方案數。即當轉移到i時,前 i - 1 位數是1 ~ i-1 中的數。此時:
如果輸入為 i,那麼 j 可由 1 ~ j-1 轉移過來,大於等於 j 的數都加一即可保證前 i 個數為1 ~ i;
如果輸入為 d,則 j 可由 j ~ i-1 轉移而來,同樣,大於等於 j 的數字都加一。
如果輸入為 ?,則將前兩種方案加起來。
在實際轉移過程中,不用涉及到大於等於 j 的數加一,只需知道轉移原理即可。
但是如果直接這樣轉移當然是不行的,還需注意到,題目中 \(n <= 10^3\),
轉移是\(n^3\),會超時。所以我們可以在轉移之前維護乙個字首和即可去掉乙個\(n\)。使時間複雜度降為\(n^2\)。如果害怕爆空間,還可以採用滾動陣列進行優化。
ps: 本題還有乙個點需要注意,由於字首和取了模,在算下降情況時,可能會出現負數,所以先加上乙個mod再取模。
至此,問題完美解決。
#include int dp[2][1005];
const int mod = 1000000007;
int main()
if(x == 'd')
if(x == '?')
x = getchar();
} int ans = 0;
for(int j = 1;j <= i;j++)ans = (ans + dp[cur][j]) % mod;
printf("%d",ans);
return 0;
}
DP 三校聯考1017T3
考場上這題做了我兩個小時。果然第一步都錯了。首先,所謂的絕對值其實可以用最優性忽略!即 a b max a b,b a 所以,不必考慮到底誰大誰小,在最優策略中,一定是合法的。然後就很簡單了 每乙個位置的貢獻分別可能為2,0,2 開頭末尾可能為 1,1 一段連續的2或 2就是一段。這麼搞一下dp就行...
NOIP模擬(11 03)T2 排列
排列 題目背景 11.03 noip 模擬t2 分析 線段樹 唯一一道可做題 我們從n 1 來確定每個數的位置,顯然,我們放入 n的時候,他一定在乙個逆序對數為 0的位置,因為它的前面不可能有比它大的,其次,如果 0位有多個,它一定在最後乙個 0位上,因為如果在前面的 0位上,後面的 0位上的數字一...
NOIP模擬 11 3 T2 排列
題目描述 有1 n的數,已知每乙個位置的逆序對,求原序列。輸入格式 第一行輸入乙個正整數n。第二行輸入n個正整數,表示pi 逆序對數字首和 輸出格式 輸出一行,共有n個數,表示原排列ai 資料範圍 對於前10 的資料 n 10。對於前30 的資料 n 1000。對於100 的資料 n 100000。...