題目鏈結
題意:給你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.遍歷每一行,並遍歷每一行的所有合理方案,若與預處理不矛盾...