毒瘤 dp 題做題記錄

2022-09-18 06:24:25 字數 2777 閱讀 7552

題目鏈結

設 \(f_\) 表示以 \(i\) 結尾的一組選擇了 \(j\) 個數,剩下的也能湊出一組時,剩下一組結尾數的最小值。

當 \(a_>a_i\) 時,\(i\) 與 \(i+1\) 可以分到一組,因此 \(f_=max(f_,f_)\)

當 \(a_>f_\) 時,\(i+1\) 能分到剩下的一組,該組原有 \(j-i\) 個數,因此 \(f_=max(f_,a_i)\)

#include #include #include #include using namespace std;

const int n = 2333;

int n, a[n], f[n][n];

int main()

if(f[n][n / 2] != 0x3f3f3f3f) printf("yes!\n");

else printf("no!\n");

}return 0;

}

題目鏈結

設 \(f_\) 表示前 \(i\) 個積木搭成的左塔和右塔差為 \(j\) 時,左邊的塔的最大高度

\(1.\) 不放如當前積木

\(f_=max(f_,f_)\)

\(2.\) 當前積木放在左邊

\(f_=max(f_,f_+a_i)\)

\(3.\) 當前積木放在右邊

\(f_=max(f_,f_)\)

注意:\(1.\) 差值可能為負數,根據資料範圍,\(j\) 直接加上 \(500000\)

\(2.\) 注意記憶體,使用滾動陣列優化

#include #include #include using namespace std;

const int p = 500000;

int n, ans = 0, a[51], f[2][1000001];

int main()

if(ans != 0) printf("%d", ans);

else printf("-1");

return 0;

}

題目鏈結

歷年真題,wa 到生活不能自理

首先考慮鏈的情況,若當前走到 \(x\)

\((s_x==')')\),計算以當前位置為結尾的合法括號串個數記為 \(f_x\)。

首先不考慮多個合法括號串並列的情況,這樣的括號串有且僅有乙個。用棧維護與其配對的前括號 \(y\),\(x\) 與 \(y\) 之間組成乙個單獨的以 \(x\) 為結尾的合法括號串 \(s\),因此 \(f_x++\);若考慮並列情況,每乙個以 \(y-1\) 為結尾的合法括號串都可以與 \(s\) 並列形成乙個新的合法括號串,\(f_x+=f_\)。綜上 \(f_x=f_+1\)。

用 \(sum_x\) 表示走到 \(x\) 時所有的合法括號串,則 \(sum_x=sum_+f_x\)。樹上的情況也大致相同,一定要注意回溯的寫法(非這樣寫不可,否則會 wa 到起飛)

#include #include #include #include using namespace std;

const int n = 2333333;

struct edge e[n];

long long n, ans = 0, st[n], sum[n], head[n], f[n], fa[n], top = 0, cnt = 0;

char s[n];

void add(long long x, long long y)

; head[x] = cnt;}

void dfs(long long x)

sum[x] = sum[fa[x]] + f[x];

ans ^= sum[x] * x;

for(long long i = head[x]; i; i = e[i].nxt) dfs(e[i].to);

if(s[x] == '(') top--;

else if(y) st[++top] = y;}

int main()

dfs(1);

printf("%lld", ans);

return 0;

}

題目鏈結

不想寫了抄題解罷...(其實是寫不好)

考慮二分答案 \(mid\),原問題變為判定是否存在一種方案,在給定天數內使得兩個軟體都能至少被完成 \(m\) 個模組。

我們設 \(f_\) 表示已經處理到第 \(i\) 個技術人員,第乙個軟體完成 \(j\) 個模組時第二個軟體最多能完成多少個模組,則狀態轉移方程為:

\(f_=max(f_+\frac)\)

表示第 \(i\) 個技術人員第乙個軟體完成 \(k\) 個模組,則第二個軟體最多完成 \(\frac\) 個模組。

最後若 \(f_>=m\) 則答案合法,時間複雜度為 \(o(nm^2log_)\)

注意邊界!

#include #include #include #include using namespace std;

const int n = 1100;

int n, m, ans, l = 0, r = 0, d1[n], d2[n], f[n][n];

bool check(int x)

int main()

while(l + 1 < r)

if(check(l)) ans = l;

else ans = r;

printf("%d", ans);

return 0;

}

數字DP做題記錄

xdu1161 一本通1588 思路 用二維陣列dp i j 表示數字取到i位的情況下,各位數字之和對題中所給n取模為j的數字個數。例如對於樣例來說,dp 1 0 表示數字最多可取到1位,各個位之和對9取模為0個數字個數,這樣的數字有兩個,即0和9。類似地,dp 1 1 1,因為1 9 1 dp 1...

ACM數學題做題記錄

僅以此部落格記錄每次遇到的數論,以便日後的複習 口胡 根本不可能再看 1.2020icpc 小公尺 網路選拔賽第一場 intelligent warehouse 數學 2.2020牛客noip賽前集訓營 提高組 第一場 牛牛的方程式 求解不定方程 3.math problem 2017廣西邀請賽 矩...

KMP做題記錄

題目太長不貼了 這道題很巧妙,給定乙個字串s,求最少在首尾新增幾個字元後,s變為乙個迴圈了n次的字串 n 1 假設我們有乙個迴圈串s abcabcabc 我們根據kmp求一次next陣列,就可以通過next strlen s 得到乙個迴圈節的位置從而求出迴圈節的長度,顯然,迴圈節能被s整除。如果s ...