dp記錄
阿新 • • 發佈:2021-12-17
https://www.luogu.com.cn/training/5011#problems
P1049:
把剩餘量轉換成最大裝多少,然後化為01揹包
CF414B:
清新。先設\(f[i][j]\)表示在\(i\)位置填\(j\)的最大方案數。
for(int i = 2; i <= k; i++){ for(int j = 1; j <= n; j++){ for(int kk = 1; kk <= j; kk++){ if(j % kk == 0){ dp[i][j] += dp[i-1][kk]; dp[i][j] %= MOD; } } } }
但\(O(n^3)\)會TLE。考慮因為當前數應是前一個數的倍數,因為 kk迴圈可以使用倍數 來減少迴圈。
for(int i = 2; i <= k; i++){
for(int j = 1; j <= n; j++){
for(int kk = 1; kk * j <= n; kk++){
f[i][kk*j] = (f[i][kk * j] + f[i-1][j]) % MOD;
}
}
}
P1586
完全揹包,\(n^2\)預處理,\(O(1)\)查詢
for(int i = 1; i * i <= 32768; i++){ for(int j = i*i; j <= 32768; j++){ for(int k = 1; k <= 4; k++){ dp[j][k] += dp[j-i*i][k-1]; } } }
P2426
設\(dp[i][j]\)表示第i個數分了j段的最大值
則有\(max(dp[i][k], dp[j-1][k-1] + abs(a[i] - a[j]) * (i-j+1))\)
for(int i = 1; i <= n; i++){ for(int j = 1; j <= i; j++){ // j ~ i 一段 for(int k = 1; k <= j; k++){ if(i == j) dp[i][k] = max(dp[i][k], a[i] + dp[i-1][k-1]); else dp[i][k] = max(dp[i][k], dp[j-1][k-1] + abs(a[i] - a[j]) * (i-j+1)); } } }
跑的飛快,人生第一次進最優解第一頁:https://www.luogu.com.cn/record/list?pid=P2426&orderBy=1&status=&page=1
P1387
wtcl\(if (a[i][j]==1) f[i][j]=min(min(f[i][j-1],f[i-1]
[j]),f[i-1][j-1])+1;\)
我本來還想想P2058那樣子
P1681同理
P2513
不會推柿子。。。。好吧是字首和優化DP
https://www.luogu.com.cn/blog/user13091/solution-p2513
P1832
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define int long long
int prime[100005];
int f[100004];
signed main(){
int n;
cin>>n;
for(int i = 2; i <= n; i++){
if(prime[i]) continue;
for(int j = 1; j * i <= n; j++){
prime[i*j] = true;
}
prime[i] = false;
}
// for(int i = 1; i <= n; i++){
// if(prime[i]) cout<<i<<' ';
// }cout<<endl;
f[0] = 1;
for(int i = 2; i <= n; i++){
if(prime[i]) continue;
for(int j = 0; j + i <= n; j++){
if(f[j]){
f[j+i] += f[j];
}
}
}
cout<<f[n]<<endl;
return 0;
}