CF 453B狀態壓縮dp

2021-07-04 06:51:01 字數 1173 閱讀 9479

題目鏈結

題意:給你n個數(1<=n<=100),每個數分別是ai(1<=ai<=30),問你求乙個數列bi,其中bi間的數兩兩的最大公約數為1(bi可能都是1),且使得

思路:既然bi可以全部取1,那麼每個bi的取值必定不超過30 - 1 + 30 = 59。由此可知我們只要知道60以內的所有數的素因子,並用數字標記的方式表示,如果這個數包含第幾個素因子,則在第幾位標1(第0位素因子是2),最後再用狀態壓縮dp處理最小值。

其中dp[i][j],表示取到第i位數,已經取過的素因子用數字的方式表示出來是j的最小值,則它由dp[i - 1][j ^ mark(k)]遞推過來,mark(k)表示數k在二進位製上包含哪些素因子,j ^ mark(k)則是不包含mark(k)中素因子的狀態。

因為還需要輸出答案,所以要儲存每乙個狀態的最優值是取哪個數獲得的,另開乙個陣列記錄這個數。

#include#define mem(a,b) memset(a,b,sizeof(a))

#define for(i,a,b) for(int i = a;i <= b;i++)

using namespace std;

typedef long long ll;

const int maxn = 75;

const int inf = 0x3f3f3f3f;

int n;

int prime[maxn];

int is[maxn];

int ori[maxn];

int len = 0;

int dp[102][1 << 17];

int bef[102][1 << 17];

void pre()

len++;

} if(len > 16)break; }}

int rec[maxn];

int main()

else if(s == 0)break;

}} int ans = 0;

for(int i = 0;i < (1 << 17);i++)//if(dp[n][ans] > dp[n][i])

ans = i;

for(int i = n;i >= 1;i--)

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

printf("\n");

}}

狀態壓縮DP

首先,我們以一道狀壓經典題tsp來引入。tsp問題 一張圖上有n個點,給定相應的鄰接矩陣,需要求出從0號節點出發,經過且只經過每個頂點一次,最後仍回到0號節點的最小邊權。思路 假設現在已訪問過的頂點集合 起點0當作還未訪問過的頂點 為s,當前所在頂點為v,用dp s v 表示從v出發訪問剩餘的所有頂...

狀態壓縮DP

theme 給定乙個n m的玉公尺田,1 n,m 12。值為0表示不能在該塊種草,為1表示可以。現在要在其上中若干草地,要求任意草地間不相鄰 沒有公共邊 問不考慮草地個數的情況下,有多少種種植的方案?solution 用dp。又範圍很小,所以考慮狀態壓縮dp,另dp i j 表示從前i行種植,最後一...

狀態壓縮DP

總結狀壓dp轉移的方法 若某個狀態下可以對下 1.按二進位制讀入資料 2.列舉所有方案,如果合理 一行中沒有兩兩相鄰的 就儲存 i i 1 3.因為每一層的狀態只受上一層影響,因此迴圈兩次所有合理方案,為每乙個方案找到一系列下一層合理方案 4.遍歷每一行,並遍歷每一行的所有合理方案,若與預處理不矛盾...